进程间的通讯方式:
管道、信号、共享内存、消息队列、信号量、套接字
1.管道
1)无名管道
特点:
不会在进程空间产生一个实实在在的管道文件;
只有用于亲缘关系的进程;
数据读出后就不存在管道;
创建无名管道的时候,会直接得到两个文件描述符,有了文件描述符就可以像管道中读取或者写入数据;
无名管道有固定的读端和写端;
读取空管道进程或者管道写满数据时,都会发生阻塞,最多65536个字节;
pipe():创建无名管道
头文件: #include <unistd.h>
原型:int pipe(int filedes[2]);(参数是一个数组,传参数组名即可)
参数:
filedes:接收打开管道文件的文件描述符0
filedes[0]:存放管道文件的读端
f iledes[1]:存放管道文件的写端
返回值:成功返回0,失败返回-1
注意:
1)调用pipe的时候必须在fork函数之前
2)只有在读端存在时向管道写入内容才有意义
3)父子进程运行的先后顺序不确定 为了保证父进程先执行可以在子进程sleep(1)
2)有名管道
特点:(其它和无名管道一样)
会创建真实管道文件
任意两个进程间都能通讯
makefifo():创建一个有名管道
头文件:
#include <sys/stat.h>
#include<sys/types.h>
原型:int mkfifo(const char * pathname,mode_t mode)
参数:
pathname:要创建的管道文件的名字(带路径)
mode:创建的FIFO文件的权限
返回值:成功返回0,失败返回-1
注:在有名管道里,读端只能以只读的方式打开文件,写端只能以只写的方式打开文件
unlink():有名管道的删除(也可以删普通文件,不能删目录)
头文件: #include <unistd.h>
原型:int unlink(const char * pathname)
参数:pathname:要删除的FIFO文件的名字(带路径)
返回值:成功返回0,失败返回-1
2.信号
1)信号是用来通知进程要干什么的。
中断是打断当前正在执行的事情转而去做另外的事情,要保护现场(压栈),另外的事情做完之后,再回过来做没有做完的事,在做这个事情之前要恢复现场(出栈)。
2)周期
产生 注册 注销 执行信号处理函数
3)信号查看
终端输入:kill -l 62个信号
部分信号类型:
2) SIGINT 键盘中断 ctrl+c
3) SIGQUIT ctrl+\
9) SIGKILL kill信号
14) SIGALRM 时钟信号
信号的相关说明
32位之前叫做不可靠信号,实时性不好 易丢失
32位之后位扩充信号,实时性较好 不易丢失
4)信号的产生
在终端输入Ctrl+c、 Ctrl+\、kill -9
内核在产生异常的时候也会发送一个信号
在进程里可以通过调用kill函数来给另一个进程发送信号
5)相关函数
kill():向指定进程发指定的信号
头文件: #include <signal.h>
原型:int kill(pid_t pid, int sig);
参数:
pid:要给谁发信号
sig:要发送的信号
返回值:成功返回0,失败返回-1
raise():向本身发送指定的信号
头文件: #include <signal.h>
原型:int raise(int sig);
参数: sig:要发送的信号类型
返回值:成功返回0,失败返回-1
pause():阻塞一个进程,直至捕捉到一个信号
头文件: #include<unistd.h>
原型:int pause(void);
参数: 无
返回值: -1
alarm():设置时间,时间到了之后产生一个14号信号,杀死自己。
头文件: #include<unistd.h>
原型:unsigned int alarm(unsigned int seconds);
参数: seconds:经过指定的时间(秒数)后产生信号
返回值: 如果调用此alarm()前,进程已经设置了闹钟时间,则返回上一个闹钟时间的剩余时间,否则返回0。
signal():设置信号处理方式
头文件: #include<signal.h>
原型:sighandler_t signal(int signum, sighandler_t handler);
参数:
signum:要操作的信号
handler:对应信号处理方式
SIG_IGN //忽略处理
signal(2,SIG_IGN);
SIG_DFL //默认处理,即交给内核
函数名 //自定义处理
返回值: 成功返回处理函数指针,失败返回SIG_ERR。