[笔记] Linux 系统调用
《趣谈 Linux 操作系统》专栏第5讲笔记
进程管理
创建进程的系统调用是 fork
。创建新的进程是通过老的进程(父进程,Parent Process)调用 fork
来实现的。新的进程也叫做子进程(Child Process)。
执行 fork
时,子进程将父进程的数据结构和程序代码都拷贝了一份。如何区分父子进程呢?通过 fork
调用的返回值来实现:如果当前进程是子进程,就返回 0;如果当前进程是父进程,就返回子进程的进程号。
如果是父进程,还接着做原来应该做的事情;如果是子进程,需要请求另一个系统调用 execve
来执行另一个程序。
父进程通过系统调用 waitpid
,将子进程的进程号作为参数传给它,就能知道子进程是否运行完成和运行的结果。
内存管理
每个进程都有自己的内存,互不干扰,有独立的进程内存空间。
进程的内存空间分为:
- 代码段(Code Segment):存放进程的程序代码。
-
数据段(Data Segment):存放进程运行过程中产生的数据。
- 其中局部变量的部分,在当前函数执行的时候起作用,当进入另一个函数时,这个变量就释放了
- 也有动态分配的,会较长时间保存,指明才销毁的,这部分称为堆(Heap)
进程的内存空间很大,对于 32 位操作系统是 4G,即2^32 Byte。
在堆里分配内存有两个常用的系统调用:
-
brk
:分配的内存数量比较小,和原来的堆的数据连在一起 -
mmap
:分配的内存数量比较大,会重新划分一块区域,不和之前的堆连在一起了
文件管理
文件操作中最重要的系统调用:
-
open
:打开已有的文件 -
close
:关闭文件 -
create
:创建文件 -
lseek
:打开文件后,使用lseek
跳到文件的某个位置 -
read
:读文件 -
write
:写文件
简单理解 Linux 中一切皆文件的思想:
- 运行的程序是二进制文件
- 配置是文本文件
- 执行命令时在 terminal 的输出是 stdout 文件
- 管道也是文件
- Socket 是文件
- 设备是文件
- 文件夹也是文件
- 查看进程运行情况时,可以看 /proc 目录下的进程号文件
- …
每个文件都有一个文件描述符(File Descriptor,简称为 FD),是一个整数。
信号处理
每种信号都定义了默认动作,例如硬件故障,默认终止(SIGKILL)。
可以通过 sigaction
系统调用,注册一个信号处理函数。
进程间通信
-
消息队列:适用于数据量小的情况。注意,这个消息队列不是那些个中间件,而是在内核中的。
- 通过
msgget
创建新队列 - 通过
msgsnd
将消息发送到队列中 - 通过
msgrcv
从队列中取消息
- 通过
-
共享内存:适用于进程间需要交互的信息比较大的情况
- 通过
shmget
创建共享内存块 - 通过
shmat
将共享内存映射到进程的内存空间 - 信号量 Semaphore 来解决多个进程间竞争共享内存中数据的问题
- 通过
网络通信
- 不同机器的网络通信遵循同一套网络协议,即 TCP/IP 协议栈。
- 通过 Socket 提供网络服务
- Socket 也是一个文件,也有其文件描述符。可以通过读写函数进行通信。
- 通过
Socket
系统调用建立 Socket
Glibc
我们写程序时不会直接使用系统调用,而是通过一个 C 库 Glibc 来做到。
Glibc 对系统调用做了封装,为编写上层程序提供 API。
问题
- 有哪些信号呢?除了自己知道的 SIGKILL,SIGHUP 等。它们的含义和应用场景
Comments