Linux进程通信方式:
(1)管道(pipe)和命名管道(FIFO)
(2)信号
(3)消息队列
(4)共享内存
(5)信号量
(6)套接字(socket)
一、管道通信
管道是单向的、先进先出、无结构的、固定大小的字节流,把一个进程的标准输出同另一个进程的标准输入连在一起。
管道通信主要是用于不同进程之间进行通信。
1、创建管道
int pipe (int fd[2])
fd[0]用于读取管道,fd[1]用于写入管道
创建一个管道后产生一个新的进程,调用成功:返回0,调用失败:返回-1
一个简单的程序:
- #include<unistd.h>
- #include<errno.h>
- #include<stdio.h>
- #include<stdlib.h>
- int main()
- {
- int pipe_fd[2];
- if(pipe(pipe_fd)<0)
- {
- printf("pipe create error/n");
- return -1;
- }
- else
- {
- printf(:pipe create success/n");
- }
- close(pipe_fd[0]);
- close(pipe_fd[1]);
- }
实际上,通常先创建一个管道,再通过fork函数创建一个子进程。
管道读写注意事项
(1)可通过打开两个管道来创建一个双向的管道。
(2)必须在系统调用fork()中调用pipe(),否则子进程不会继承文件描述符。
(3)使用半双工管道时,任何关联的进程都必须共享一个相关的祖先进程。(管道存在于内核中,其他进程无法寻址它)
2、标准流管道
(1)、接口函数popen()创建;
返回值:若成功,返回一个新的文件流;
若无法创建进程或管道,返回NULL。
(2)、接口函数pclose()关闭;
返回值:返回系统调用的wait4()的状态;
如果stream无效,或wait4()调用失败,返回-1。
(3)、FILE *popen (char *command, char *type)………………*type:"r"或"w"
int pclose(FILE *stream)
3、有名管道(FIFO)
(1)命名管道是在文件系统中作为一个特殊设备文件而存在;
(2)不同祖先进程之间可以通过管道共享数据;
(3)当共享管道的进程执行完所有的I/O操作以后,命名管道将继续保存在文件系统中以便以后使用。
命名管道的创建
#include<sys/types.h>
#include<sysy/stat.h>
int mkfifo(const char *pathname, mode_t mode);
返回:若成功0,失败-1。
一旦mkfifo创建了一个FIFO,就可用open、close、read、write
FIFO相关出错信息
EACCES 无存取权限
EEXIST 指令文件不存在
ENAMETOOLONG 路径名太长
ENOENT 包含的目录不存在
ENOSPC 文件系统剩余空间不足
ENOTDIR 文件路径无效
EROFS 指定文件存在于只读文件系统中
二、信号通信
信号是软中断,用于在一个或多个进程之间传递异步信号
(1)按下某些终端键,产生信号;
(2)硬件异常产生信号:如除数为0,无效存储访问等;
(3)进程用kill函数将信号发送给另一个进程或进程组;
接收、发送的进程所有者相同,或尽头信号的进程所有者为超级用户。
(4)用户可用kill命令将信号发送给其他进程;
(5)检测到某种软件条件已经发生,并将其通知有关进程时产生信号。
主要的信号源:
(1)异常 进程运行过程中出现异常
(2)其他进程 一个进程向另一个或组进程发送信号
(3)终端中断: ctrl+c ctrl+/ 等
(4)作业控制:前台、后台进程管理(状态转换等)
(5)分配额:CPU超时,文件大小超限
(6)通知:通知进程事件发生(I/O就绪)
(7)报警:计时器到期
Linux中的信号(30个以上)