趣谈Linux操作系统-01Linux操作系统综述

Linux操作系统综述

  • 03-你可以把Linux内核当成一家软件外包公司的老板
  • 04-快速上手几个Linux命令:每家公司都有自己的黑话
    • 用户与密码
    • 浏览文件
    • 安装软件
      • 原始的下载安装包安装的方式(rpm/dpkg)
        • 查看已安装的软件
          • 从多个结果中找到你要的
            • grep
            • more/less
        • 删除软件
      • "软件管家"yum/apt
        • 搜索
        • 安装
        • 卸载
        • 服务端地址
          • sed命令的使用
          • 使用sed更换apt源
      • 安装软件的本质
        • 最原始的安装方式
          • 下载
          • 解压
            • 关于解压的相关命令的补充
          • 设置环境变量
            • export(仅在当前命令行的会话中管用)
            • .bashrc(每次登录都会执行)
    • 运行软件
      • 通过shell在交互命令行里面运行
      • 后台运行
        • nohup
        • 输出
        • 关闭进程
      • 以服务的方式运行
    • 关机与重启
    • 小结
  • 05-学会几个系统调用:咱们公司能接哪些类型的项目?
    • 进程管理
    • 内存管理
    • 文件管理
    • 信号处理
    • 进程间通信
      • 消息队列(Message Queue)
      • 共享内存
        • 信号量机制Semaphore
    • 公司间沟通与网络通信
    • 查看源代码中的系统调用
    • 中介与Glibc
    • 小结
    • 课堂练习

课程:趣谈Linux操作系统

03-你可以把Linux内核当成一家软件外包公司的老板

04-快速上手几个Linux命令:每家公司都有自己的黑话

Linux命令简写和全称
Linux常见命令缩写
我的实验环境win10下的wsl,
互通的环境:
C:\Users\zhangjiequan-home\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs\home\zjqroot

cmd -h 查看简要帮助文档
man cmd 查看详细帮助文档(man, manual pages,手册页)
如 passwd -h;man passwd

用户与密码

passwd #Pass Word 改密码等,eg:passwd testname
useradd #加用户 eg:user add testname
su [username] #Swith user  切换用户 eg:su root, su testname

Windows 10 WSL Ubuntu 系统的 root 密码
cat /etc/passwd
cat /etc/group

浏览文件

cd就是change directory,就是切换目录;
cd .表示切换到当前目录;
cd …表示切换到上一级目录;
ls,list (win使用dir),可以列出当前目录下的文件。
ls -a
ls -l 用列表的方式列出文件

# ls -l
drwxr-xr-x 6 root root    4096 Oct 20  2017 apt
-rw-r--r-- 1 root root     211 Oct 20  2017 hosts

第一个字段的第一个字符是文件类型。如果是“-”,表示普通文件;如果是d,就表示目录。当然还有很多种文件类型,咱们后面遇到的时候再说,你现在先记住我说的这两个就行了。

第一个字段剩下的9个字符是模式,其实就是权限位(access permission bits)。
3个一组,每一组rwx表示“读(read)”“写(write)”“执行(execute)”。
如果是字母,就说明有这个权限;如果是横线,就是没有这个权限。

这三组分别表示文件所属的用户权限、文件所属的组权限以及其他用户的权限。例如,上面的例子中,-rw-r–r–就可以翻译为,这是一个普通文件,对于所属用户,可读可写不能执行;对于所属的组,仅仅可读;对于其他用户,也是仅仅可读。如果想改变权限,可以使用命令chmod 711 hosts(Change mode 改变模式)。

第二个字段是硬链接(hard link)数目,这个比较复杂,讲文件的时候我会详细说。
第三个字段是所属用户,第四个字段是所属组。
第五个字段是文件的大小,第六个字段是文件被修改的日期,最后是文件名。你可以通过命令chown改变所属用户,chgrp改变所属组。

安装软件

原始的下载安装包安装的方式(rpm/dpkg)

RPM:Red hat package manager
dpkg:Debian package manage(是 Debian 的项目创始人 Ian Murdock 和他的妻子 Debra 的名字缩写。;是Linux的一个版本。;Debian 是一套为了您的计算机所设计的自由操作系统。Debian 使用 Linux 核心;但大部份的基本工具则来自 GNU 计划;)
趣谈Linux操作系统-01Linux操作系统综述_第1张图片
类似win下的exe,可以下载rpm或者deb。这个就是Linux下面的安装包。

为什么有两种呢?因为Linux现在常用的有两大体系,一个是CentOS体系,一个是Ubuntu体系,前者使用rpm,后者使用deb。

在Linux上面,没有双击安装这一说,因此想要安装,我们还得需要命令。CentOS下面使用rpm -i jdk-XXX_linux-x64_bin.rpm进行安装,Ubuntu下面使用dpkg -i jdk-XXX_linux-x64_bin.deb。其中-i就是install的意思。

查看已安装的软件

在Linux下面,凭借rpm -qadpkg -l就可以查看安装的软件列表,-q就是query,a就是all,-l的意思就是list。
如果真的去运行的话,你会发现这个列表很长很长,很难找到你安装的软件。

从多个结果中找到你要的
grep

如果你知道要安装的软件包含某个关键词,可以用一个很好用的搜索工具grep

rpm -qa | grep jdk,这个命令是将列出来的所有软件形成一个输出。| 是管道,用于连接两个程序,前面rpm -qa的输出就放进管道里面,然后作为grep的输入,grep将在里面进行搜索带关键词jdk的行,并且输出出来。grep支持正则表达式,因此搜索的时候很灵活,再加上管道,这是一个很常用的模式。同理dpkg -l | grep jdk也是能够找到的。

more/less

如果你不知道关键词,可以使用rpm -qa | more和rpm -qa | less这两个命令,它们可以将很长的结果分页展示出来。这样你就可以一个个来找了。

我们还是利用管道的机制。more是分页后只能往后翻页,翻到最后一页自动结束返回命令行,less是往前往后都能翻页,需要输入q返回命令行,q就是quit。

删除软件

如果要删除,可以用rpm -e和dpkg -r。-e就是erase,-r就是remove。

"软件管家"yum/apt

yum,yellowdog updater modified 的缩写。yellowdog 是一个 Linux 的 distribution。
apt,Advanced Packaging Tool

搜索

你可以根据关键词搜索,例如搜索jdk、yum search jdk和apt-cache search jdk(apt search jdk),可以搜索出很多很多可以安装的jdk版本。如果数目太多,你可以通过管道grep、more、less来进行过滤。

安装

选中一个之后,我们就可以进行安装了。你可以用yum install java-11-openjdk.x86_64和apt-get install openjdk-9-jdk来进行安装。

卸载

安装以后,如何卸载呢?我们可以使用yum erase java-11-openjdk.x86_64和apt-get purge openjdk-9-jdk。

服务端地址

Linux允许我们配置从哪里下载这些软件的,地点就在配置文件里面。

对于CentOS来讲,配置文件在/etc/yum.repos.d/CentOS-Base.repo里。

[base]
name=CentOS-$releasever - Base - 163.com
baseurl=http://mirrors.163.com/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=http://mirrors.163.com/centos/RPM-GPG-KEY-CentOS-7

对于Ubuntu来讲,配置文件在/etc/apt/sources.list里。

deb http://mirrors.163.com/ubuntu/ xenial main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ xenial-security main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ xenial-updates main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ xenial-proposed main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ xenial-backports main restricted universe multiverse

注意改后需要执行apt update

这里为什么都是163.com呢?因为Linux服务器遍布全球,不能都从一个地方下载,最好选一个就近的地方下载,例如在中国,选择163.com,就不用跨越重洋了。

sed命令的使用

Linux命令大全-sed命令
Linux sed 命令

使用sed更换apt源

WSL-Ubuntu18.04 LTS 更换apt源为阿里源

安装软件的本质

其实无论是先下载再安装,还是通过软件管家进行安装,都是下载一些文件,然后将这些文件放在某个路径下,然后在相应的配置文件中配置一下。例如,在Windows里面,最终会变成C:\Program Files下面的一个文件夹以及注册表里面的一些配置。对应Linux里面会放的更散一点。例如,
主执行文件:会放在/usr/bin或者/usr/sbin下面,
其他的库文件:会放在/var下面,
配置文件:会放在/etc下面。

最原始的安装方式

所以其实还有一种简单粗暴的方法,就是将安装好的路径直接下载下来,然后解压缩成为一个整的路径。在JDK的安装目录中,Windows有jdk-XXX_Windows-x64_bin.zip,这是Windows下常用的压缩模式。Linux有jdk-XXX_linux-x64_bin.tar.gz,这是Linux下常用的压缩模式。

下载

如何下载呢?Linux上面有一个工具wget,后面加上链接,就能从网上下载了。

解压

下载下来后,我们就可以进行解压缩了。Windows下可以有winzip之类的解压缩程序,Linux下面默认会有tar程序。如果是解压缩zip包,就需要另行安装。

yum install zip.x86_64 unzip.x86_64
apt-get install zip unzip

如果是tar.gz这种格式的,通过tar xvzf jdk-XXX_linux-x64_bin.tar.gz就可以解压缩了。

关于解压的相关命令的补充

Linux 学习之创建、删除文件和文件夹命令
六、Linux常用命令之压缩打包篇(gzip、gunzip、tar、zip、bzip2)
1、gzip有两个特点:
(1)、它只能压缩文件,不能压缩目录
(2)、不保留源文件 newfile1.gz newfile1不在了
看起来没什么用,过时的产物?
gunzip和gzip是一对,压缩和解压
2、tar

tar -zcf filename.tar.gz ./* #压缩当前目录下的所有文件
tar -zxvf ./filename.tar.gz -C ./b #解压在目录C下

不产生后缀名,一般手动指定为*.tar.gz(用file a.tar.gz会有提示gzip compressed data,不指定后缀,无法通过ls直观看到文件类型)
3、压缩解压命令zip (注意:该命令不自动产生后缀名,会保留源文件,用得最多的压缩命令,但不是自带,可以用sudo apt install zip等安装)

zip services.zip /etc/services
unzip services.zip -b ./disDic

4、压缩解压命令:bzip2(不能压缩目录,但由于有-k选项,所以可以保留源文件)

设置环境变量

win上设置环境变量
对于Windows上jdk的安装,如果采取这种下载压缩包的格式,需要在系统设置的环境变量配置里面设置JAVA_HOME和PATH。
在Linux也是一样的,通过tar解压缩之后,也需要配置环境变量

export(仅在当前命令行的会话中管用)

可以通过export命令来配置

export JAVA_HOME=/root/jdk-XXX_linux-x64
export PATH=$JAVA_HOME/bin:$PATH

export命令仅在当前命令行的会话中管用,一旦退出重新登录进来,就不管用了。

.bashrc(每次登录都会执行)

有没有一个地方可以像Windows里面可以配置永远管用呢?

在当前用户的默认工作目录,例如/root或者/home/cliu8下面,有一个.bashrc文件,这个文件是以点开头的,这个文件默认看不到,需要ls -la才能看到,a就是all。每次登录的时候,这个文件都会运行,因而把它放在这里。这样登录进来就会自动执行。当然也可以通过source .bashrc手动执行。

要编辑.bashrc文件,可以使用文本编辑器vi,也可以使用更加友好的vim。如果默认没有安装,可以通过yum install vim及apt-get install vim进行安装。

运行软件

我们都知道Windows下的程序,如果后缀名是exe,双击就可以运行了。

通过shell在交互命令行里面运行

Linux不是根据后缀名来执行的。它的执行条件是这样的:只要文件有x执行权限,都能到文件所在的目录下,通过./filename运行这个程序。当然,如果放在PATH里设置的路径下面,就不用./了,直接输入文件名就可以运行了,Linux会帮你找。

这是Linux执行程序最常用的一种方式,通过shell在交互命令行里面运行。

这样执行的程序可能需要和用户进行交互,例如允许让用户输入,然后输出结果也打印到交互命令行上。这种方式比较适合运行一些简单的命令,例如通过date获取当前时间。这种模式的缺点是,一旦当前的交互命令行退出,程序就停止运行了。

这样显然不能用来运行那些需要“永远“在线的程序。比如说,运行一个博客程序,我总不能老是开着交互命令行,博客才可以提供服务。一旦我要去睡觉了,关了命令行,我的博客别人就不能访问了,这样肯定是不行的。

后台运行

于是,我们就有了Linux运行程序的第二种方式,后台运行。

nohup

这个时候,我们往往使用nohup命令。这个命令的意思是no hang up(不挂起),也就是说,当前交互命令行退出的时候,程序还要在。

当然这个时候,程序不能霸占交互命令行,而是应该在后台运行。最后加一个&,就表示后台运行:

nohup command &

输出

另外一个要处理的就是输出,原来什么都打印在交互命令行里,现在在后台运行了,输出到哪里呢?输出到文件是最好的。

最终命令的一般形式为nohup command >out.file 2>&1 &
解释一下其中新增的>out.file 2>&1
这里面,“1”表示文件描述符1,表示标准输出,“2”表示文件描述符2,意思是标准错误输出,“2>&1”表示标准输出和错误输出合并了。合并到哪里去呢?到out.file里。

关闭进程

那这个进程如何关闭呢?我们假设启动的程序包含某个关键字,那就可以使用下面的命令。

ps -ef |grep 关键字  |awk '{print $2}'|xargs kill -9

从这个命令中,我们多少能看出shell的灵活性和精巧组合。

其中:
ps -ef:可以单独执行,列出所有正在运行的程序
grep:上面我们介绍过了,通过关键字找到咱们刚才启动的程序。
awk:工具可以很灵活地对文本进行处理,这里的awk '{print $2}'是指第二列的内容,是运行的程序ID。
xargs kill -9:我们可以通过xargs传递给kill -9,也就是发给这个运行的程序一个信号,让它关闭。如果你已经知道运行的程序ID,可以直接使用kill关闭运行的程序。如使用ps -ef得到进程id为576,可使用kill -9 576来关闭这个进程。(一开始对这个xargs kill -9不懂,看了Linux中的管道和xargs之后,补充一下:xargs kill -9前面的一坨东东,其实就是得到了一个进程id,最后用xargs把id传给kill -9,效果是kill -9 ${id})

以服务的方式运行

在Windows里面还有一种程序,称为服务。这是系统启动的时候就在的,我们可以通过控制面板的服务管理启动和关闭它。
趣谈Linux操作系统-01Linux操作系统综述_第2张图片
Linux也有相应的服务,这就是程序运行的第三种方式,以服务的方式运行。例如常用的数据库MySQL,就可以使用这种方式运行。

例如在Ubuntu中,我们可以通过apt-get install mysql-server的方式安装MySQL,然后通过命令systemctl start mysql启动MySQL,通过systemctl enable mysql设置开机启动。之所以成为服务并且能够开机启动,是因为在/lib/systemd/system目录下会创建一个XXX.service的配置文件,里面定义了如何启动、如何关闭。

在CentOS里有些特殊,MySQL被Oracle收购后,因为担心授权问题,改为使用MariaDB,它是MySQL的一个分支。通过命令yum install mariadb-server mariadb进行安装,命令systemctl start mariadb启动,命令systemctl enable mariadb设置开机启动。同理,会在/usr/lib/systemd/system目录下,创建一个XXX.service的配置文件,从而成为一个服务。

即无论Ubuntu还是CentOS,用都是用systemctl启动和设置开机启动。

(wsl下的Ubuntu不能用systemctl,启动可以用:

sudo service mysql start

开机启动暂时不知道怎么搞。
解决Win10-Ubuntu子系统启动MySQL报错的问题
System has not been booted with systemd as init system (PID 1). Can’t operate)

systemd的机制十分复杂,这里咱们不讨论。如果有兴趣,你可以自己查看相关文档。

关机与重启

最后咱们要学习的是如何关机和重启。这个就很简单啦。shutdown -h now是现在就关机,reboot就是重启。

(wsl下重启:

net stop LxssManager
net start LxssManager

关机自然是:

net stop LxssManager

ref:如何重启 Windows 10 子系统(WSL) ubuntu)

小结

05-学会几个系统调用:咱们公司能接哪些类型的项目?

其实Linux命令也是一个程序,只不过代码是别人写好的,你直接用就可以了。你可以自己试着写写代码,通过代码把Linux系统用起来,这样印象会更深刻。

无论是别人写的程序,还是你写的程序,运行起来都是进程。程序使用的是系统调用,系统调用决定了这个操作系统好用不好用、功能全不全。下面介绍都有哪些”系统调用“:

进程管理

首先,我们得有个项目,那就要有立项服务。对应到Linux操作系统中就是创建进程。

创建进程的系统调用叫fork。这个名字很奇怪,中文叫“分支”。为啥启动一个新进程叫“分支”呢?

在Linux里,要创建一个新的进程,需要一个老的进程调用fork来实现,其中老的进程叫作父进程(Parent Process),新的进程叫作子进程(Child Process)。

当父进程调用fork创建进程的时候,子进程将各个子系统为父进程创建的数据结构也全部拷贝了一份,甚至连程序代码也是拷贝过来的。按理说,如果不进行特殊的处理,父进程和子进程都按相同的程序代码进行下去,这样就没有意义了。

所以,我们往往会这样处理:对于fork系统调用的返回值,如果当前进程是子进程,就返回0;如果当前进程是父进程,就返回子进程的进程号。这样首先在返回值这里就有了一个区分,然后通过if-else语句判断,如果是父进程,还接着做原来应该做的事情;如果是子进程,需要请求另一个系统调用-execve来执行另一个程序,这个时候,子进程和父进程就彻底分道扬镳了,也即产生了一个分支(fork)了。

同样是“先拷贝,再修改”的策略,你可能会问,新进程都是父进程fork出来的,那到底谁是第一个呢?

启动的时候先创建一个所有用户进程的“祖宗进程”。这个在讲系统启动的时候还会详细讲,我这里先不多说。

有时候,父进程要关心子进程的运行情况,这毕竟是自己身上掉下来的肉。有个系统调用-waitpid,父进程可以调用它,将子进程的进程号作为参数传给它,这样父进程就知道子进程运行完了没有,成功与否。

所以说,所有子项目最终都是老板,也就是祖宗进程fork过来的,因而它要对整个公司的项目执行负最终的责任。

内存管理

在操作系统中,每个进程都有自己的内存,互相之间不干扰,有独立的进程内存空间

对于进程的内存空间来讲,放程序代码的这部分,我们称为代码段(Code Segment)

对于进程的内存空间来讲,放进程运行中产生数据的这部分,我们称为数据段(Data Segment)。其中局部变量的部分,在当前函数执行的时候起作用,当进入另一个函数时,这个变量就释放了(栈?);也有动态分配的,会较长时间保存,指明才销毁的,这部分称为堆(Heap)

一个进程的内存空间是很大的,32位的是4G,64位的就更大了,我们不可能有这么多物理内存。就像一个公司的会议室是有限的,作为老板,你不可能事先都给项目组分配好。哪有这么多会议室啊,一定是需要的时候再分配。

所以,进程自己不用的部分就不用管,只有进程要去使用部分内存的时候,才会使用内存管理的系统调用来登记,说自己马上就要用了,希望分配一部分内存给它,但是这还不代表真的就对应到了物理内存。只有真的写入数据的时候,发现没有对应物理内存,才会触发一个中断,现分配物理内存。

这里我们介绍两个在堆里面分配内存的系统调用,brkmmap

当分配的内存数量比较小的时候,使用brk,会和原来的堆的数据连在一起,这就像多分配两三个工位,在原来的区域旁边搬两把椅子就行了。当分配的内存数量比较大的时候,使用mmap,会重新划分一块区域,也就是说,当办公空间需要太多的时候,索性来个一整块。

文件管理

程序、文档、照片等,哪怕Linux关机再开机也能不丢的,就需要放在文件系统里面。

文件之所以能做到这一点,一方面是因为介质,另一方面是因为格式。公司之所以强调资料库,也是希望将一些知识固化为标准格式,放在一起进行管理,无论多少人来人走,都不影响公司业务。

文件管理其实花样不多,拍着脑袋都能想出来,无非是创建、打开、读、写等。
对于文件的操作,下面这六个系统调用是最重要的:

  • 对于已经有的文件,可以使用open打开这个文件,close关闭这个文件;
  • 对于没有的文件,可以使用creat创建文件;
  • 打开文件以后,可以使用lseek跳到文件的某个位置;
  • 可以对文件的内容进行读写,读的系统调用是read,写是write

但是别忘了,Linux里有一个特点,那就是一切皆文件

  • 启动一个进程,需要一个程序文件,这是一个二进制文件
  • 启动的时候,要加载一些配置文件,例如yml、properties等,这是文本文件;启动之后会打印一些日志,如果写到硬盘上,也是文本文件
  • 但是如果我想把日志打印到交互控制台上,在命令行上唰唰地打印出来,这其实也是一个文件,是标准输出stdout文件
  • 这个进程的输出可以作为另一个进程的输入,这种方式称为管道,管道也是一个文件。
  • 进程可以通过网络和其他进程进行通信,建立的Socket,也是一个文件。
  • 进程需要访问外部设备,设备也是一个文件。
  • 文件都被存储在文件夹里面,其实文件夹也是一个文件。
  • 进程运行起来,要想看到进程运行的情况,会在/proc下面有对应的进程号,还是一系列文件。

每个文件,Linux都会分配一个文件描述符(File Descriptor),这是一个整数。有了这个文件描述符,我们就可以使用系统调用,查看或者干预进程运行的方方面面

所以说,文件操作是贯穿始终的,这也是“一切皆文件”的优势,就是统一了操作的入口,提供了极大的便利。

信号处理

在项目运行过程中,不一定都是一帆风顺的,很可能遇到各种异常情况。作为老板,处理异常情况的能力是非常重要的,所以办事大厅也一定要包含这部分服务。

当项目遇到异常情况,例如项目中断,做到一半不做了。这时候就需要发送一个信号(Signal)给项目组。经常遇到的信号有以下几种:

  • 在执行一个程序的时候,在键盘输入“CTRL+C”,这就是中断的信号,正在执行的命令就会中止退出;
  • 如果非法访问内存,例如你跑到别人的会议室,可能会看到不该看的东西;
  • 硬件故障,设备出了问题,当然要通知项目组;
  • 用户进程通过kill函数,将一个用户信号发送给另一个进程。

当项目组收到信号的时候,项目组需要决定如何处理这些异常情况。

对于一些不严重的信号,可以忽略,该干啥干啥,但是像SIGKILL(用于终止一个进程的信号)和SIGSTOP(用于中止一个进程的信号)终?中?区别??是不能忽略的,可以执行对于该信号的默认动作。每种信号都定义了默认的动作,例如硬件故障,默认终止;也可以提供信号处理函数,可以通过sigaction系统调用,注册一个信号处理函数。

提供了信号处理服务,项目执行过程中一旦有变动,就可以及时处理了。

进程间通信

消息队列(Message Queue)

首先就是发个消息,不需要一段很长的数据,这种方式称为消息队列(Message Queue)。由于一个公司内的多个项目组沟通时,这个消息队列是在内核里的,我们可以通过msgget创建一个新的队列,msgsnd将消息发送到消息队列,而消息接收方可以使用msgrcv从队列中取消息。

共享内存

当两个项目组需要交互的信息比较大的时候,可以使用共享内存的方式,也即两个项目组共享一个会议室(这样数据就不需要拷贝来拷贝去)。大家都到这个会议室来,就可以完成沟通了。这时候,我们可以通过shmget创建一个共享内存块,通过shmat将共享内存映射到自己的内存空间,然后就可以读写了。

信号量机制Semaphore

但是,两个项目组共同访问一个会议室里的数据,就会存在“竞争”的问题。如果大家同时修改同一块数据咋办?这就需要有一种方式,让不同的人能够排他地访问,这就是信号量的机制Semaphore。

这个机制比较复杂,我这里说一种简单的场景。

对于只允许一个人访问的需求,我们可以将信号量设为1。当一个人要访问的时候,先调用sem_wait。如果这时候没有人访问,则占用这个信号量,他就可以开始访问了。如果这个时候另一个人要访问,也会调用sem_wait。由于前一个人已经在访问了,所以后面这个人就必须等待上一个人访问完之后才能访问。当上一个人访问完毕后,会调用sem_post将信号量释放,于是下一个人等待结束,可以访问这个资源了。

公司间沟通与网络通信

同一个公司不同项目组之间的合作搞定了,如果是不同公司之间呢?也就是说,这台Linux要和另一台Linux交流,这时候,我们就需要用到网络服务。

不同机器的通过网络相互通信,要遵循相同的网络协议,也即TCP/IP网络协议栈。Linux内核里有对于网络协议栈的实现。如何暴露出服务给项目组使用呢?

网络服务是通过套接字Socket来提供服务的。Socket这个名字很有意思,可以作“插口”或者“插槽”讲。虽然我们是写软件程序,但是你可以想象成弄一根网线,一头插在客户端,一头插在服务端,然后进行通信。因此,在通信之前,双方都要建立一个Socket。

我们可以通过Socket系统调用建立一个Socket。Socket也是一个文件,也有一个文件描述符,也可以通过读写函数进行通信。

好了,我们分门别类地规划了这么多办事大厅的服务,如果这些都有了,足够我们成长为一个大型跨国公司了。

查看源代码中的系统调用

你如果问,这里的系统调用列举全了吗?其实没有,系统调用非常多。我建议你访问https://www.kernel.org下载一份Linux内核源代码。因为在接下来的整个课程里,我讲述的逻辑都是这些内核代码的逻辑。
(

sudo lsb_release -a
cat /proc/version

ubuntu查看系统版本和linux内核版本)

对于64位操作系统,找到unistd_64.h文件,里面对于系统调用的定义,就是下面这样。

#define __NR_restart_syscall	  0
#define __NR_exit		  1
#define __NR_fork		  2
#define __NR_read		  3
#define __NR_write		  4
#define __NR_open		  5
#define __NR_close		  6
#define __NR_waitpid		  7
#define __NR_creat		  8
......

中介与Glibc

如果你做过开发,你会觉得刚才讲的和平时咱们调用的函数不太一样。这是因为,平时你并没有直接使用系统调用。虽然咱们的办事大厅已经很方便了,但是为了对用户更友好,我们还可以使用中介Glibc,有事情找它就行,它会转换成为系统调用,帮你调用。

Glibc是Linux下使用的开源的标准C库,它是GNU发布的libc库。Glibc为程序员提供丰富的 API,除了例如字符串处理、数学运算等用户态服务之外,最重要的是封装了操作系统提供的系统服务,即系统调用的封装

每个特定的系统调用对应了至少一个Glibc封装的库函数,比如说,系统提供的打开文件系统调用sys_open对应的是Glibc中的open函数

有时候,Glibc一个单独的API可能调用多个系统调用,比如说,Glibc提供的printf函数就会调用如sys_open、sys_mmap、sys_write、sys_close等等系统调用。

也有时候,多个API也可能只对应同一个系统调用,如Glibc下实现的malloc、calloc、free等函数用来分配和释放内存,都利用了内核的sys_brk的系统调用。

小结

学了这么多系统调用,我们还是用一个图来总结一下。
趣谈Linux操作系统-01Linux操作系统综述_第3张图片

课堂练习

有个命令strace,常用来跟踪进程执行时系统调用和所接收的信号。你可以试一下咱们学过的命令行,看看都执行了哪些系统调用。
答:
使用以下命令查看ls -la来跟踪这个命令执行时的系统调用和所接收的信号。

strace ls -la

执行后,得知有如下系统调用:
execve
brk
mmap
access
open
fstat
mmap
close
read
stat
write
lseek
lstat
getxattr
socket
connect
mprotect

你可能感兴趣的:(Code)