进程间通信

文章详细介绍了进程间通信的几种方式,包括匿名管道和有名管道的使用场景及工作原理,强调了管道的阻塞特性、文件描述符的共享以及管道大小的限制。同时提到了内存映射作为另一种通信手段,其速度快且支持同步和不同步选项。在实际应用中,需注意读写操作的同步和资源管理。
摘要由CSDN通过智能技术生成

 通信:一个进程和另一个进程发送数据;

父子进程,无关系进程;

进程是资源分配单元;不同进程的资源是独立的,没有关联;不能在一个进程中直接访问另一个进程的资源;

 

   匿名管道用在有关系的进程之间,有名管道一般用在没有关系的进程之间;

 

 

 有关系进程,文件描述符表共享;

例如:

父进程文件描述符5写数据;6读数据;

子进程文件描述符5读数据;6写数据

 就可以实现进程间通信;

 管道的数据结构:线性队列;

用逻辑的方式设置为环形队列; 

 

 pipe管道:两个文件描述符pipefd ;pipefd[0]:读;pipefd[1]:写;

数据写到管道缓冲区;

 

 注意:匿名管道只适用于有关系的进程之间;

在父子进程通信时;要在fork之前建立管道;这样两个进程都有读写管道

 子进程写数据到pipefd[1];

父进程从读取端读取数据;

 管道默认是堵塞的,管道中没有数据堵塞,直到读取完

每隔一秒发送一次数据;

父进程读了之后写;子进程写了之后读

 

 查看管道缓冲的大小:默认4k

 获取管道大小的函数:fpathconf();

获取文件配置的值;

 

 如果去掉sleep收到的是自己的数据;

有sleep的时候子进程写完CPU就被父进程抢过去执行了

没有sleep那就是子进程继续执行,写完数据又继续读数据;

 在匿名管道中,一般不会两边都写和两边都读;

 在实际操作中一个读一个写:

例如父进程用来读,那么将父进程的写端进行关闭;子进程的写读端进行关闭

关闭读端:close(pipefd[0]);

关闭写端:close(pipefd[1]); 

 

将标准输出文件重定向到管道的写端;

 

 再去执行ps aux;

 

 execlp函数族:会将当前进程用户区的数据替换,输出ps命令,参数为aux;

如果失败打印错误信息并退出;

 在父进程中从管道中提取数据;输出;

close(pipefd[1])

char buf[1024]={0};

int len=read(pipefd[1],buf,sizeof(buf)-1);

sizeof(buf)-1去掉一个NULL字符;

 

 问题:只读出了1024-1=1023个字节的数据;也就只输出这么多;

应该定义一个循环读;

输出完了清空数据:memset();

 

 最后wait回收子进程的资源;

 问题2:管道大小只有4k写满了就结束了;所以也应该设置循环写;

管道的读写特点和管道设置为非阻塞

使用管道时要注意:假设都是阻塞I/O操作;

1.所有指向管道写端的文件描述符都关闭了(管道写端引用计数为0),进程从管道的读端读数据,那么管道中剩余的数据被读取之后,再次read会返回0;就像读到末尾一样;

2.如果有指向管道写端的文件描述符,(管道写端引用计数大于0),而没有往管道中写数据;那么管道中剩余的数据被读取后再次read会阻塞;直到管道中有数据可以读才读数据并返回数据;

3.如果所有指向管道读端都关闭了;这个时候有进程向管道写端写数据时,该进程会收到一个信号:SIGPIPE会导致进程异常终止;

4.如果有指向管道读端的文件描述符没有关闭,而持有管道读端的进程也没有从管道中读数据;有进程往管道中写数据,那么在管道中被写满的时候再次write会被阻塞,直到有数据被读;

 ​​​​​​​

 读管道设置非阻塞;

注意:buf输出后要清空memset(buf,0,1024);

 子进程写数据后睡眠;

父进程读到数据输出;

读不到继续读,

 有名管道

 

 有名管道有文件实体,但是fifo中的内容并不存在于文件中,而是内存中;

 

 

通过命令创建FIFO文件; 

mode和open中一样,会和u_mask按位与;

 

 

 

 实现两个管道通信;

在创建之前可以判断一下,文件是否存在;存在就不创建了;

 access()

 ​​​​​​​

 

 ​​​​​​​

 

 

 注意:两个管道都要打开才会开始读写;

 读写过程中任意管道关闭另一个管道都会关闭;

 

 有名管道实现简单版聊天功能

 

 ​​​​​​​

 只能一人发一条--不能把读写放在一个进程中;这样总有一个是阻塞的;

可以把写管道读管道放在不同的进程中(父子进程);

例如父进程中读,子进程中写,或者相反;这样就可以同步运行;

内存映射

 ​​​​​​​

内存映射快比磁盘操作;

当进程1对内存中的数据修改,对内存2去读取相应内存中的数据也就已经修改相当于在进行通信;

mmap:映射;可以实现有关系的内存映射也可以没有关系的;

munmap:解除映射;

头文件:#include<sys/mman.h>

mmap:

 MAP_SHARED:同步,进程间通信要打开共享;映射区的数据会自动和磁盘文件进行同步

MAP_PRIVATE:不同步,内存映射区数据变了对原来的文件不会改变,会重新创建一个新的文件(copy on write)写时复制,读时共享;

fd:需要映射的哪个文件的文件描述符

        -通过open得到,open的是一个磁盘文件;

        -文件大小不能为0;并且open时的权限不能和prot参数有冲突;

offset:偏移量(一般不用,一般指定4k的整数倍)0,不偏移;

munmap:解除映射;

返回值:成功返回内存的首地址;失败返回(void*)-1;

参数:addr:释放的内存首地址

length:要释放的内存大小,和mmap的一样;

 注意:内存映射区不阻塞;

lseek(fd,0,seek_end):获取文件大小;

 

创建子进程:

 

 关闭内存映射区

父进程读数据,子进程写数据;父进程在回收完子进程的数据后在读取数据;

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值