进程间通信:管道 信号量 共享内存 消息队列 套接字
管道文件:读端只能读,写端只能写,写入管道的数据在内存中,但管道文件的属性等都在外存(必须两个文件打开)
管道文件分为有名管道(mkfifo)和无名管道(pipe)
mkfifo fifo
:创建管道文件fifo
管道为空,读阻塞;管道写满,写会阻塞。
写端关闭,读端返回0
read()=0 。
管道读端关闭,写端写入数据触发异常
有名管道
:可以在任意两个进程间通信
无名管道
:只能在父子进程间使用
管道的通信方式:半双工(相当于对讲机)某时刻只能有一个进行。
其他还有单工(只能a到b)和全双工(同一时刻两者皆可进行)
有名管道的例子
两个终端执行两个程序a,c输入,b.c读
a.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<fcntl.h>文件头文件
void sig_fun(int sig)
{
printf("sig=%d\n",sig);
}
int main()
{
signal(SIGPIPE,sig_fun);当读进程关闭后写进程会受到SIGPIPE信号
int fdw=open("fifo",O_WRONLY);open失败返回-1
assert(fdw!=-1);
printf("fdw=%d\n",fdw);
while(1)
{
char buff[128]={0};
printf("input:\n");
fgets(buff,128,stdin);
if(strncmp(buff,"end",3)==0)
{break;}
write(fdw,buff,strlen(buff));
}
close(fdw);
exit(0);
}
b.c文件
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<fcntl.h>文件头文件
int main()
{
int fdr=open("fifo",O_RDONLY);
assert(fdr!=-1);
printf("fdr=%d\n",fdr);
while(1)
{
char buff[128]={0};
int n=read(fdr,buff,127);
if(n==0){break};
printf("buff=%d,n=%d\n",buff,n);
}
close(fdr);
exit(0);
}
无名管道的例子
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<string.h>
#include<fcntl.h>
#include<signal.h>
int main()
{
int fd[2];fd[0]存放读的描述符,fd[1]存放写的描述符
int res=pipe(fd);返回-1为失败
assert(res!=-1);
pid_t pid=fork();
assert(pid!=-1);
if(pid==0)子进程读
{
close(fd[1]);关闭读端
char buff[128]={0};
read(fd[0],buff,127);
printf("child read:%s\n",buff);
}else父进程写
{
close(fd[0]);关闭写
char buff[128]={0};
fgets(buff,128.stdin);
write(fd[1],buff,strlen(buff));
close(fd[1]);
}
}