常見的進程間通信方式
傳統進程間通信方式
- 無名管道(pipe)
- 有名管道(fifo)
- 信號(signal)
System V IPC 對象
- 共享內存(share memory)
- 消息隊列(message queue)
- 信號燈(semaphore)
System V IPC 對象
- 套接字(socket)
特點: - 只能用於具有血緣關係的進程間通信
- 半雙工的通信模式,有固定的讀端和寫端fd[0]爲讀端 fd[1]爲寫端,fd爲整形數組最小有兩個元素
- 管道是一種特殊的文件,纔在於內存中,在文件系統中不可見,可以用文件io函數來讀寫操作。如write(寫)、read(讀)。
無名管道的創建
父子進程間通信
/*************************************************************************
> 功能:利用無名管道實現兩個具有血緣關係的進程通信
************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
int main()
{
pid_t pid;
int fd[2];
int rd;
int wr;
char buf[1024]={0};
//創建無名管道
int ret=pipe(fd);
if(ret<0)
{
perror("pipe error");
exit(-1);
}
//創建子進程
pid= fork();
if(pid<0)
{
perror("fork error");
exit(-2);
}
//子進程讀 /關閉寫端close fd[1]
if(pid==0)
{
close (fd[1]);
if((rd=read(fd[0],buf,sizeof(buf))) > 0)
{
printf("無名管道讀到的東西是%s\n",buf);
}
close(fd[0]);
exit(0);
}
//父進程寫 /關閉讀端 close fd[0]
if(pid>0)
{
memset(buf,0,sizeof(buf));
gets(buf);
close(fd[0]);
if( (wr=write(fd[1],buf,sizeof(buf)))>0)
{
printf("這次寫進去了%s\n",buf);
waitpid(pid,NULL,0);
exit(0);
}
close(fd[1]);
}
exit(0);
}
兄弟進程間通信
/*************************************************************************
> File Name: pipe.c
> Author:
> 功能:利用無名管道實現兩個具有血緣關係的進程通信
> Created Time: Tue 13 Aug 2019 08:12:22 PM PDT
************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<wait.h>
int main()
{
pid_t pid;
pid_t pid1;
int fd[2];
int rd;
int wr;
char buf[1024]={0};
//創建無名管道
int ret=pipe(fd);
if(ret<0)
{
perror("pipe error");
exit(-1);
}
//創建子進程
pid= fork();
pid1=fork();
if(pid<0 || pid1<0)
{
perror("fork error");
exit(-1);
}
//子進程讀 /關閉寫端close fd[1]
if(pid==0)
{
close (fd[1]);
if((rd=read(fd[0],buf,sizeof(buf))) > 0)
{
printf("我是弟弟 ");
printf("無名管道是%s\n",buf);
}
close(fd[0]);
exit(10);
}
//子進程1寫 /關閉讀端close fd[0]
if(pid1==0)
{
memset(buf,0,sizeof(buf));
gets(buf);
close(fd[0]);
if( (wr=write(fd[1],buf,sizeof(buf)))>0)
{
printf("我是哥哥\n");
}
close(fd[1]);
exit(11);
}
//父進程
int status=0;
int status1=0;
if(pid>0)
{
sleep(1);
wait(&status);
printf("進程的退出狀態是%d\n",WEXITSTATUS(status));
wait(&status1);
printf("進程1的退出狀態是%d\n",WEXITSTATUS(status1));
}
exit(0);
}
無名管道使用需要注意的點
- 無名管道只能用在具有親緣關係的進程間通信
- 是一種半雙工的模式;意思是同一個時刻,只能讀或者寫;
- 只有在管道讀端存在時,寫端纔有意義;
- 管道沒有數據時,讀端會一直阻塞;
- 讀完數據就立馬消失;
- 不能用fseek跳轉;
- 只存在於內存中,在文件系統不可見;
- 遵循先進先出的規則。