【1】进程间通信方式
-
基本进程通信方式
无名管道 、有名管道、信号 -
system V IPC对象
共享内存、信号灯集、消息队列 -
BSD
套接字
【2】无名管道
-
特点:
-
只能用于具有亲缘关系的进程之间的通信
-
无名管道是单工管道,半双工的通信模式,具有固定的读端和写端
-
管道可以看成是一种特殊的文件,对于它的读写可以使用文
件IO如read、write函数。 -
管道是基于文件描述符的通信方式。当一个管道建立时,
它会创建两个文件描述符fd[0]
和fd[1]
。其中fd[0]
固定用于读管道,而fd[1]
固定用于写管道。 -
无名管道的操作属于一次性操作,如果对无名管道进行读操作,
数据会被全部读走 -
无名管道的大小是固定的,管道一旦满,写操作就会导致进程阻塞,
管道的大小是64K
。只有读出大于等于4K
之后,写操作解除阻塞。 -
当管道中无数据时,执行读操作,读操作阻塞。
-
无名管道不保证操作的原子性,如果当前管道,
满足读写条件,读写可同时进行。 -
向无名管道中写去数据,将读端关闭,管道破裂,
进程收到信号(SIGPIPE
),默认这个信号会将进程杀死 。 -
当管道中有数据,将写端关闭,读操作可以执行,
之后数据读完,可以继续读取(非阻塞),直接返回0。 -
无需
open
,但需手动close
。 -
不支持如
lseek()
操作。队列形式,先进先出,属于一次性操作。
-
-
函数
int pipe(int fd[2])
功能:创建无名管道
参数:文件描述符 fd[0]:读端 fd[1]:写端
返回值:成功 0
失败 -1 -
注意事项:
- 当管道中无数据时,读操作会阻塞
- 管道中装满数据写阻塞,一旦有4k空间,写继续
- 只有在管道的读端存在时,向管道中写入数据才有意义。否则,
会导致管道破裂,向管道中写入数据的进程将收到内核传来的SIGPIPE
信号
(通常Broken pipe错误)。
【3】有名管道:
-
特点:
- 有名管道可以使互不相关的两个进程互相通信。
- 有名管道可以通过路径名来指出,并且在文件系统中可见,
但内容存放在内存中。不存到磁盘上。 - 进程通过文件IO来操作有名管道,需要用
open
打开 - 有名管道以队列的方式先进先出
- 一次性操作,不支持
lseek()
-
相关函数:
通过命令创建mkfifo my_fifo
$ mkfifo filename -m mode
mkfifo myfifo -m 0666
(创建一个命名管道myfifo,其权限为0666)
创建管道文件成功后,只是对应在磁盘中有这个文件了,
并没有对应的内存,只有在一个进程用open打开这个文件后,
这个管道缓冲区(数组)才会开辟存在。close关闭后其缓冲区释放不存在。int mkfifo(const char *filename,mode_t mode);
功能:创健有名管道
参数:filename
:有名管道文件名
mode
:权限
返回值:成功:0
失败:-1,并设置errno号
注意对错误的处理方式:
如果错误是file exist
时,注意加判断,如:
if(errno == EEXIST)
…
-
注意:
以O_WRONLY
打开管道,写阻塞
以O_RDONLY
打开管道,读阻塞
以O_RDWR
打开管道,管道中没有内容,读阻塞
#include <stdlib.h>
int system(const char *command);
功能:调用可执行命令,实现命令功能。
system("rm fifo")
;删除管道文件
【4】信号:
-
概念:
- 信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式
- 信号可以直接进行用户空间进程和内核进程之间的交互,内核
进程也可以利用它来通知用户空间进程发生了哪些系统事件。 - 如果该进程当前并未处于执行态,则该信号就由内核保存起来,
直到该进程恢复执行再传递给它;如果一个信号被进程设置为阻塞,
则该信号的传递被延迟,直到其阻塞被取消时才被传递给进程。
-
用户进程对信号的响应方式:
- 忽略信号:对信号不做任何处理,但是有两个信号不能忽略:
即SIGKILL
及SIGSTOP
。 - 捕捉信号:定义信号处理函数,当信号发生时,执行相应的处理函数。
- 执行缺省操作:Linux对每种信号都规定了默认操作
- 忽略信号:对信号不做任何处理,但是有两个信号不能忽略:
-
信号:
kill -l
SIGINT
:ctrl+c
终止信号
SIGQUIT
:ctrl+\
终止信号
SIGTSTP
:ctrl+z
暂停信号
SIGALRM
:闹钟信号 收到此信号后定时结束,结束进程
SIGCHLD
:子进程状态改变,父进程收到信号
SIGKILL
:杀死信号
SIGSTOP
:停止信号
SIGUSR1、SIGUSR2-->未定义默认功能的信号
-
相关函数:
-
int kill(pid_t pid, int sig);
功能:信号发送
参数:pid
:指定进程
sig
:要发送的信号
返回值:成功 0
失败 -1 -
int raise(int sig);
功能:进程向自己发送信号
参数:sig
:信号
返回值:成功 0
失败 -1 -
unsigned int alarm(unsigned int seconds)
功能:在进程中设置一个定时器
参数:seconds
:定时时间,单位为秒
返回值:如果调用此alarm()前,进程中已经设置了闹钟时间,则
返回上一个闹钟时间的剩余时间,否则返回0。
注意:一个进程只能有一个闹钟时间。如果在调用alarm时
已设置过闹钟时间,则之前的闹钟时间被新值所代替 -
int pause(void);
功能:用于将调用进程挂起直到收到信号为止。 -
void (*signal(int signum, void (*handler)(int)))(int);
或者:
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler)
功能:信号处理函数(注册信号)
参数:signum
:要处理的信号
handler
:SIG_IGN
:忽略该信号。
SIG_DFL
:采用系统默认方式处理信号。
自定义的信号处理函数指针
返回值:成功:设置之前的信号处理方式
失败:SIG_ERR
-