进程间的通信应用也是很广泛的,比如后台进程和GUI界面数据传递,发送信号关机,Ctrl+C终止正在运行的程序等。
Linux进程间通信机制分三类:数据交互,同步,信号。理解了这些机制才能灵活运用操作系统提供的IPC工具。
本章以常用的管道(包括有名管道和无名管道),System V IPC(消息队列,共享内存,信号灯),套接字(UNIX域套接字和网络套接字)为例来说明Linux进程通信常用的方法,本文档中介绍的只是一小部分,如果想深入了解可以去翻看专业的书籍。本章代码在ipc/文件夹下。
1无名管道
无名管道是最古老的进程通信方式,有如下两个特点:
1.只能用于有关联的进程间数据交互,如父子进程,兄弟进程,子孙进程,在目录中看不到文件节点,读写文件描述符存在一个int型数组中。
2.只能单向传输数据,即管道创建好后,一个进程只能进行读操作,另一个进程只能进行写操作,读出来字节顺序和写入的顺序一样。
pipe():创建无名管道:
#include <unistd.h>
int pipe(int pipefd[2]);
参数含义:
一个int型数组,表示管道的文件描述符,pipefd[0]为读,pipefd[1]为写,如图 1.1:
返回值:成功返回0,失败返回-1。
无名管道使用步骤:
1.调用pipe()创建无名管道;
2.fork()创建子进程,一个进程读,使用read(),一个进程写,使用write()。
实验:
创建无名管道,父进程从终端获取数据,写入管道,子进程从管道读数据并打印出来。
pipe.c:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 32
int main(int argc, const char *argv[])
{
int ret;
int fd[2];
pid_t pid;
char buff[LEN];
ret = pipe(fd);//创建无名管道
if(-1 == ret){
perror("pipe");
return -1;
}
pid = fork();
if(pid < 0){
perror("fork");
return -1;
}else if(pid == 0){
while(1){
memset(buff,0,LEN);
ret = read(fd[0],buff,LEN);//从管道读
if(ret < 0) continue;
printf("fd[0]: %s\n",buff);
}
}else if(pid > 0){
char str[LEN];
while(1){
fgets(str,LEN,stdin);
ret = write(fd[1],str,LEN);//向管道写入
}
}
return 0;
}
执行结果: