Linux--进程间通信、IPC、管道

目录

1.进程间通信的方法

2.IPC机制

1.有命管道:

1.简介

5.管道的特点

6.循环写读

2.无名管道

1.简介

2.代码

4.总体特点

5.管道实现图


1.进程间通信的方法

(1)管道

(2)信号量

(3)共享内存

(4)消息队列

(5)套接字

2.IPC机制

1.有命管道:

1.简介

1.管道简介

|命令:

举例:ps -ef|grep "sleep"

d9e64fed74814597b6bbf7117c6fd8a1.png

 720cd40a77594667b412dbf7a2c3c261.png

 

两个进程通信,比如a,b进程,a向管道中写入数据,b读取数据;

管道的分类:有名管道和无名管道

区别:有名管道在任意两个进程间通信,无名管道在父子进程间通信;

2.有名管道的创建

创建的命令:mkfifo 管道名

5134a3e272344f46a4d73d5c9ba7e639.png 打开管道:open();

读数据:read();

写入数据:write();

关闭管道:close();

3.有名管道演示进程间通信思考

如果进程 a 要将从键盘获取的数据传递给另一个进程 b, 用已具备的知识思考应该如何完成 ?

1.文件可以,但是不建议;

2.管道:

创建管道之后,它会在内存上分配一块空间,表面上看把数据写入管道中了,实际上是把数据写入内存中了。另外一个程序是从内存中读取数据的,所以效率是比较高的。

管道文件:大小永远为0;

4.有名管道实现进程间通信

又名命名管道;

代码:

a.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <fcntl.h>
int main()
{
	int fd = open("fifi", O_WRONLY);
	assert(fd != -1);
	printf("fd=%d\n", fd);
	write(fd, "hello", 5);
	close(fd);
}

b.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <fcntl.h>
int main()
{
	int fd = open("./fifi", O_RDONLY);
	assert(fd != -1);
	printf("fd=%d\n", fd);
	char buff[128] = { 0 };
	read(fd, buff, 127);
	printf("read:%s\n", buff);
	close(fd);
}

 结果:

996855cbdce04c43a906bfdab808c2e8.png 

5.管道的特点

(1)管道必须读,写进程同时open,否则会阻塞;

(2)如果管道中没有数据,那么read就会阻塞;

(3)管道的写端关闭,读read返回值为0

(4)管道打开的时候只有只读和只写方式,读写方式是未定义的;

6.循环写读

代码:

a.c

#include <string.h>
#include <assert.h>
#include <fcntl.h>
int main()
{
	int fd = open("fifi", O_WRONLY);
	assert(fd != -1);
	while (1)
	{
		printf("input:\n");
		char buff[128] = { 0 };
		fgets(buff, 128, stdin);
		if (strncmp(buff, "end", 3) == 0)
		{
			break;
		}
		write(fd, buff, strlen(buff));
	}
	close(fd);
}

b.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <fcntl.h>
int main()
{
	int fd = open("./fifi", O_RDONLY);
	assert(fd != -1);
	printf("fd=%d\n", fd);
	while (1)
	{
		char buff[128] = { 0 };
		if (read(fd, buff, 127) == 0)
		{
			break;
		}
		printf("read:%s\n", buff);
	}
	close(fd);
}

结果:

d1db9bed88aa49428945a53da095dedd.png

2.无名管道

1.简介

无名管道,pipe创建无名管道;它只能进行父子间的通信;

使用pipe创建无名管道,只能进行父子间的通信;

pipe是一个系统调用

int pipe(int fds[2]);
//pipe()成功返回 0,失败返回-1
//fds[0]是管道读端的描述符
// fds[1]是管道写端的描述符
//规定

2.代码

父进程写入数据,子进程读取数据;

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
int main()
{
    int fd[2];
	assert(pipe(fd)!=-1);
	pid_t pid=fork();//先open,再frok,父子进程共享打开的文件描述符
	assert(pid!=-1);

    if(pid==0)
	{
		close(fd[1]);
		char buff[128]={0};
		read(fd[0],buff,127);
		printf("child read:%s\n",buff);
		close(fd[0]);
	}
	else
	{
		close(fd[0]);
		write(fd[1],"hello",5);
		close(fd[1]);
	}
	exit(0);
}

4.总体特点

(1)管道必须读,写进程同时open,否则会阻塞;

(2)如果管道没有数据,那么read也会阻塞;

(3)管道的写端关闭,读read返回值为0;

(4)管道打开的时候只有只读和只写两种方式,读写方式打开是未定义的;

(5)管道是半双工的(某一时刻只能选择一个方向)(面试重点)(通信方式有单工,半双工,全双工)

(6)无论有名还是无名,写入管道的数据都在内存中(面试重点)

(7)有名管道和无名管道的区别:有名可以在任意进程间通信,无名主要在父子进程间通信(面试重点)

(8)管道的读端关闭,写会产生异常(发送信号SIGPIPE)(可以改变信号的响应方式验证一下)

25da14432f8947d4a7fd7a810d5fb2aa.png

 验证这个信息,只需要改变信号的响应方式:

#include <signal.h>
void fun(int sig)
{
	printf("sig=%d\n",sig);
}
int main()
{
	signal(SIGPIPE,fun);
	...
}

5.管道实现图

4edce3ce07c349e4a4994cbd3ed7e3da.png

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值