传统进程间通信
通过文件实现进程间通信 必须人为保证先后顺序 A--->硬盘---> B(B不知道A什么时候把内容传到硬盘中)
1.无名管道
2.有名管道
3.信号
IPC进程间通信
4.消息队列
5.共享内存
6.信号灯集
7.socket通信
一、无名管道(亲缘关系的进程 64K)
原理:
如果A和B进程想要通过无名管道通信,那就必须在内核空间创建一个无名管道(64K),A和B进程必须是亲缘关系的进程,A进程向管道的一端写数据,B进程可以从管道的另外一端读数据。在A进程和B进程进行数据传输的时候是不允许使用lseek函数的。无名管道是半双工的通信方式。如果A进程一直向管道中写数据写满64K的时候A进程阻塞,直到B进程读一部分数据之后A才能继续写。如果B进程在读数据的时候,无名管道是空的,B进程阻塞。(PS:使用无名管道时,不会创建管道文件,使用有名管道文件,会创建)
API
int pipe(int pipefd[2]);
功能:创建一个无名管道
参数:
@pipefd[2]:返回的管道的两端
pipefd[1]:写端
pipefd[0]:读端
返回值:成功返回0,失败返回-1置位错误码
实例
#include <head.h>
// 子进程从终端读取字符串 通过无名管道 父进程读 然后打印到终端
int main(int argc, const char *argv[])
{
int pipefd[2];
if (-1 == pipe(pipefd))
{
perror("pipe error");
exit(-1);
};
char buff[128] = {0};
pid_t pid;
pid = fork();
if (pid == -1)
{
perror("fork error");
exit(-1);
}
else if (pid == 0)
{
// 子进程
close(pipefd[0]); // 关闭子进程的读端 因为父子进程同时各自拥有读和写 把对应的关一个
while (1)
{
memset(buff, 0, sizeof(buff));
fgets(buff, sizeof(buff), stdin); // 从终端读取数据
if ((buff[strlen(buff) - 1]) == '\n')
{
buff[strlen(buff) - 1] = '\0';
}
write(pipefd[1], buff, sizeof(buff)); // 将读到的写入到管道
if (strcmp(buff, "quit") == 0)
{
break;
}
}
close(pipefd[1]);
exit(0);
}
else
{
// 父进程
close(pipefd[1]); // 关闭父进程的写端
while (1)
{
memset(buff, 0, sizeof(buff));
read(pipefd[0], buff, sizeof(buff)); // 父进程从管道中读
printf("父进程data:%s\n", buff);
if (strcmp(buff, "quit") == 0)
{
break;
}
}
close(pipefd[2]);
wait(NULL);
}
return 0;
}
结果
二、有名管道(任意进程间的通信 64K)
有名管道可以实现任意进程间的通信,有名管道的大小也是64K,有名管道也是不支持lseek,有名管道也是半双工的通信方式。有名管道创建之后会在用户空间产生一个管道文件(p),这个管
道文件是在内存上存储的。如果A和B两个进程想要通过有名管道通信,就打开管道文件,向管道中写向管道中读就可。
API
int mkfifo(const char *pathname, mode_t mode);
功能:创建有名管道
参数:
@pathname:有名管道文件的路径及名字
@mode: 管道文件的权限(mode & ~umask)
返回值:成功返回0,失败返回-1置位错误码
实例
01mkfifo.c
#include <head.h>
#define FIFO_PATH "./myfifo"
int main(int argc,const char * argv[])
{
//创建管道文件
if(mkfifo(FIFO_PATH,0666)==-1){
perror("mkfifo error");
exit(-1);
}
//阻塞等待读写
getchar();
//删除管道文件
char buff[128]={0};
snprintf(buff,sizeof(buff),"rm -rf %s",FIFO_PATH);
system(buff);
return 0;
}
02read.c
#include <head.h>
#define FIFO_PATH "./myfifo"
int main(int argc, const char *argv[])
{
int fd;
char buff[128] = {0};
if (-1 == (fd = open(FIFO_PATH, O_RDONLY)))
{
perror("open error");
exit(-1);
}
while (1)
{
memset(buff, 0, sizeof(buff));
read(fd, buff, sizeof(buff));
printf("read:[%s]\n", buff);
if (strcmp(buff, "quit") == 0)
{
break;
}
}
close(fd);
return 0;
}
03write.c
#include <head.h>
#define FIFO_PATH "./myfifo"
int main(int argc, const char *argv[])
{
int fd;
char buff[128] = {0};
if (-1 == (fd = open(FIFO_PATH, O_WRONLY)))
{
perror("open error");
exit(-1);
}
while (1)
{
memset(buff, 0, sizeof(buff));
printf("input:");
fgets(buff,sizeof(buff),stdin);
if(buff[strlen(buff)-1]=='\n'){
buff[strlen(buff)-1]='\0';
}
write(fd, buff, sizeof(buff));
if (strcmp(buff, "quit") == 0)
{
break;
}
}
close(fd);
return 0;
}
结果
三、信号
信号软件层面对中断一种模拟,用户可以给进程发送信号,内核也可以给进程发送信号,进程对信号的响应方式有三种:捕捉,默认,忽略
标签:int,pipefd,间通信,管道,Linux,进程,sizeof,buff From: https://blog.csdn.net/CSDN_DU666666/article/details/139904835