【1】进程间的通信
传统的进程间通信方式
无名管道、有名管道、信号
System V IPC对象
共享内存、消息队列、信号灯集
BSD
套接字
【2】无名管道
1.只能用于具有亲缘关系的进程之间通信
2.半双工的通信模式,具有固定的读端和写端
3.管道可以看成是一种特殊的文件,对于它的读写可以用文件IO,read、write
#include <unistd.h>
int pipe(int pipefd[2]);
功能:创建一个无名管道
参数:pipefd[] 是一个数组,用来存放两个文件描述符
pipefd[0] 读端
pipefd[1] 写端
返回值:成功返回0 失败返回-1
【3】管道的读写特性
读特性:
1.写端存在
管道中有数据,读数据
管道中没有数据,读阻塞
2.写端不存在
管道中没有数据,读不到内容
管道中有数据,读相应的数据
写特性
1.读端存在
可以向管道中写,写满了写会阻塞
2.读端不存在
向管道中写会造成管道断裂,进程直接结束
练习:测试当前系统无名管道的大小? (65536字节)
【特别提醒】:管道不能用lseek进行偏移
练习:利用管道进行进程间通信,父进程当写端,子进程当读端,实现输入和打印
1.父子进程?
2.无名管道、父子进程怎么就都知道了?
3.对于无用的文件描述符记得关闭
【4】有名管道
管道可以在文件系统中看到,可以用于两个互不相关的进程通信
1.mkfifo命令
mkfifo 管道名
2.mkfifo函数
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
功能:创建有名管道
参数:pathname 管道的名字
mode 指定有名管道的权限
返回值:成功返回0 失败返回-1
【5】有名管道的特点
1.一台机器上的任意两个进程间通信
2.全双工的模式,读写都是一端
3.有名管道在文件系统可见,可以用文件IO来操作
4.有名管道也不支持lseek
5.当一个进程使用open函数O_RDONLY或O_WRONLY打开时,open函数会阻塞,直到另一个进程以对应的方式打开
练习:利用有名管道,实现两个不同进程通信,拷贝文件
1.进程1:从源文件中读,写到管道中
2.进程2:从管道中读,写到目标文件中
【6】信号
信号是在软件层次上对中断机制的一种模拟,它是进程间唯一的一种异步通信方式
信号由内核产生,递交给用户空间来处理
kill -l
SIGKILL 不能阻塞、处理、忽略
SIGSTOP 不能阻塞、处理、忽略
用户进程对信号的响应方式
1.忽略信号:对信号不做任何处理,但是有两个不能忽略SIGKILL和SIGSTOP
2.执行缺省操作:执行默认操作
3.捕捉信号:当信号发生时,执行我们自己规定的事情
kill 信号 pid
kill -9 pid
默认发送15信号
【7】信号相关函数
信号注册函数:
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
功能:注册一个信号(回调函数)
参数:signum 信号
handler 函数指针变量
1.自己定义一个函数
2.SIG_IGN 忽略
3.SIG_DFL 缺省操作
返回值:成功返回函数指针,失败返回SIG_ERR
理解过程:
int *p;--》void (*)(int) sighandler_t
typedef (int *) p; p是一个数据类型--》typedef void (*)(int) sighandler_t
p q;--》sighandler_t handler;
handler--》void fun(int )
发送信号:
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
功能:给进程发送信号
参数:pid 进程的pid
sig 要发送的信号
返回值:成功返回0 失败返回-1
#include <signal.h>
int raise(int sig);
功能:给自己发送信号
参数:sig 要发送的信号
返回值:成功返回0,失败非0
定时器函数:
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
功能:给进程设定时间,一个进程只能设定一个时间
参数:seconds 设定的秒数 0代表取消闹钟
返回值:成功:如果调用alarm()前,进程已经设定过闹钟,则返回上一个闹钟的剩余时间
否则返回0;