1.Linux进程通信机制:
- 管道
- 信号量
- 消息队列
- 共享内存
- socket通信
2.管道
管道其实质是由内核管理的一个缓冲区
形象地认为管道的两端连接着两个进程:
管道分为:
- 匿名管道:只能用于有亲缘关系的进程间通信,进程退出后管道会被销毁。
- 命名管道:命名管道与进程的联系较弱,相当于一个读写内存的接口,进程退出后,命名管道依然存在。
2.1匿名管道
匿名管道的使用流程如下:
①在进程中创建匿名管道,pipe函数;
②关闭进程中不使用的管道端口,close函数;
③在待通信的进程中分别对管道的读、写端口进行操作,read/write函数;
④关闭管道,close函数。
2.1.1pipe函数
#include <unistd.h>
int pipe(int pipefd[2]);
功能:创建匿名管道
参数说明: pipefd:传入参数,一个文件描述符数组;Linux将管道抽象为一个特殊文件。
返回说明:
成功:返回0.
不成功:返回-1。
案例分析:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
int tempFd[2];//定义文件描述符数组
int tempRet=pipe(tempFd);//创建管道
if(tempRet == -1){
perror("pipe");
exit(1);
}
pid_t tempPid=fork();
if(tempPid > 0){//父进程—读
close(tempFd[1]);//关闭写端
char tempBuf[64]={0};
tempRet = read(tempFd[0], tempBuf, sizeof(tempBuf));//读数据
close(tempFd[0]);
write(STDOUT_FILENO, tempBuf, tempRet);//将读到的数据写到标准输出
wait(NULL);
} else if(tempPid == 0){//子进程—写
close(tempFd[0]);//关闭读端
char *tempStr="hello,pipe\n";
write(tempFd[1], tempStr, strlen(tempStr)+1);//写数据
close(tempFd[1]);
}//of if
return 0;
}//of main
2.1.2dup2函数
案例分析:
使用管道实现兄弟进程间通信,兄弟进程实现命令“ls | wc –l”的功能。
#include <unistd.h>
int dup2(int oldfd, int newfd);
- 其功能是将参数oldfd的文件描述符复制给newfd
- 若函数调用成功则返回newfd
- 否则返回-1,并设置errno。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
int tempFd[2];
int tempRet = pipe(tempFd);
if(tempRet == -1){
perror("pipe err");
exit(1);
}//of if
int i;
pid_t tempPid, tempWpid;
for(i=0; i<2; i++){//2个子
if((tempPid = fork()) == 0){
break;
}//of if
}//of if
if(2 == i){//父进程,回收子进程
close(tempFd[0]); //关闭读
close(tempFd[1]); //关闭写
tempWpid = wait(NULL);
printf("wait child 1 success,pi