进程间的通信(管道,共享内存)

前言

今天我们讨论进程之间的通信,利用管道(pipe)和共享内存(share memory)实现数据流通。

1.管道(pipe)

管道是最古老也是最容易理解的通信方式,它有两个限制

  1. 一个管道只能在一个方向上传送数据
  2. 管道只能在拥有共同父进程(指同一个登录shell)的进程间使用

也就是说在开始于一个登录shell以及由该shell派生出来的所有进程中可以运用管道通信。如图
这里写图片描述

#include<unistd.h>
int pipe(int filedes[2]);//创建成功返回0,失败返回-1,filedes[0]为读,filedes[1]为写,其内容为文件描述符

下面给出管道通信实例代码

#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
int fd[2];
pid_t pid;
char buf[64]="asdasdasdasdasd";
char buf2[64];
if(0!=pipe(fd))
    perror("fail to create pipe"); //创建管道失败
pid=fork();//派生进程
if(pid<0)//派生进程失败
{perror("fail to create process");}
else if(pid>0)//父进程
{
close(fd[0]);//关闭管道的读
write(fd[1],buf,strlen(buf));//向管道写字符串
close(fd[1]);//关闭管道的写

}
else//子进程
{
close(fd[1]);//关闭管道的写
read(fd[0],buf2,64);//从管道读出字符串
puts(buf2);
close(fd[0]);//关闭管道的读

}


}

最后运行结果如图
这里写图片描述


2.共享内存

共享内存是在内存空间中开辟一段空间,供不同的进程访问。与管道相比,能在多个不同进程间共享,也不受上述管道的两种限制。可以同时对一段内存进行读与写。而且可以传输更大的数据。示意图如下
这里写图片描述

共享内存有关函数如下
1.shmget()创建共享内存

#include<sys/ipc.h>
#include<sys/shm.h>
int shmget(key_t key,size_t size,int shmflg)

若成功申请返回值为共享内存的ID,申请失败则为-1。
shmget()向OS申请一段共享内存,其中key是系统唯一的关键字可以用ftok()生成,也可以自定义,但一定得是唯一存在。size是需要多大的共享内存字节数,shmflg是操作方式。

shmflg取值意义如下

0:取共享内存标识符,若不存在则函数会报错
IPC_CREAT:当shmflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存,返回此共享内存的标识符
IPC_CREAT|IPC_EXCL:如果内核中不存在键值 与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存则报错
SHM_R 共享内存可读
SHM_W共享内存可写

2.void *shmat( ) 获得一个共享内存ID对应的内存起始地址。

#include<sys/ipc.h>
#include<sys/shm.h>
void *shmat(int shmid,const void* shmaddr,int shmflg)

若成功获得地址则返回值是地址,反之则为(void *)-1
参数shmid 是共享内存的ID,shmaddr参数指定了共享内存的地址,若为0,表示需要系统决定共享内存地址。shmflg见上。

3.int shmdt()从程序中分离一块共享内存

#include<sys/ipc.h>
#include<sys/shm.h>
int shmdt(const void * shmaddr)

函数作用:将shmaddr所指向的共享内存从程序中分离出来,不再随着程序的终止而被抹去。

实例代码见下

//write.c-->gcc write.c -o  write
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>

void main()
{
    int shmid;
    char *ptr;
    char *str="qweqweqweqweqwe";
    shmid=shmget(0x2f,1024,SHM_W|SHM_R|IPC_CREAT|IPC_EXCL);

    if(-1==shmid)
        perror("fail to create share memory");
    ptr=(char *)shmat(shmid,0,0);
    if((void *)-1==ptr)
        perror("fail to get share memory");
    strcpy(ptr,str);
    shmdt(ptr);

}

//read.c-->gcc read.c -o   read
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>

void main()
{
    int shmid;
    char *ptr;

    shmid=shmget(0x2f,1024,SHM_W|SHM_R|IPC_EXCL);

    if(-1==shmid)
        perror("fail to create share memory");
    ptr=(char *)shmat(shmid,0,0);
    if((void *)-1==ptr)
        perror("fail to get share memory");
    puts(ptr);
    shmdt(ptr);

}

运行结果如下
这里写图片描述

但是当我们再一次执行write程序时会发生报错。其错误原因就是内存中已经有了0x2f这个key值,而我们实例中没有删除共享内存。使用命令ipcs查看目前共享资源。
这里写图片描述

使用命令ipcrm释放指定的共享内存
这里写图片描述
再次执行实例再不报错

写在最后

今天我们对进程间的通信进行了一定的挖掘,对进程间数据的共享掌握了一些方法。下次我们将讨论通信机制主角——信号

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值