Linux下到IPC(进程间通信方法比较)



下面涉及到到一些函数,都可以用man命令来获取信息,比如man shmget,或者man 2 write.

进程作为linux系统中分配资源的最小单位,进程间到协作和通信用的范围比较广泛。 进程间通信的方法有以下几种:

  • PIPE(半双工管道)
  • FIFO (命名管道)
  • 信号量
  • 消息队列
  • 共享内存
  • 信号

PIPE主要是用在父子进程之间到通信,是最初级的IPC通信方式,它主要是调用pipe()函数来生成管道,它返回两个文件描述符fd[0],fd[1],fd[0]是读端口,fd[1]是写端口,当你要用到写端口时候就必须把读端口关闭,反之亦然。PIPE是阻塞性质到,当你发送到东西大于128K到时候,它是原子操作,当接受数据不及时到话,发送端将会一直阻塞,等到数据接收完全。

 

FIFO可以用shell命令mkfifo先创建一个,或者用C函数mkfifo()来实现一个,FIFO一旦创建完成,你就可以以操作文件到方式来操作它了,大概流程是:

      打开FIFO==>读写操作==>关闭FIFO。

因为linux下到设备都是以文件形式存在的,所以很容易理解上述过程。

消息队列是在linux内核中建立消息链表来提供给进程间的通信。下面介绍下消息队列的基本操作。消息队列用来存放传送消息到结构在linux/msg.h里面定义:

[cpp]  view plain copy
  1. struct msgbuf {  
  2.         long mtype;         /* type of message */  
  3.         char mtext[1];      /* message text */  
  4. };  

上面的mtype是消息的类型,接受消息的mtype必须和发送端的mtype一样,当你写代码要发送消息的时候,得参照这个定义个结构体,long mtype是不能变的,下面的mtext[1]可以变成你想要到数字,用来存放消息。

消息队列还有一个由内核维护到结构struct msqid_ds,具体可以阅读头文件里到代码。当你要创建一个消息队列到时候,先得获得一个key,这个key通过ftok获得,不同进程之间利用这个key来区分队列,下面就简单介绍下具体操作:

ftok(pathname,project)生成一个key,不同进程之间用ftok函数的里面参数一样时,key是一样的,利用这个通信不同进程可以认识队列。

msgget(key,msgflag)创建一个队列或者找到相等的key的队列,flag主要是IPC_CREAT和IPC_EXCL,之用IPC_CREAT的时候,如果系统已经有key相等到队列,则返回那个key的队列,EXCL参数和CREAT一起用的时候,如果系统有那个key到队列,则返回一个失败值。

msgsnd(msgid,*msgp,size,flag) 该函数用来发送消息,msgid是创建队列时返回到标示,msgp就是你定义的存放消息的结构体,size是消息长度,它不包括mtype长度。举例如下:

[c-sharp]  view plain copy
  1.  struct msgmbuf {  
  2.                 long mtype;  
  3.                 char mtext[20];  
  4.         };  
  5. .........  
  6. ........  
  7. (*msg_mbuf).mtype=10;  
  8. memcpy((*msg_mbuf).mtext,"message test",sizeof("message test")));  
  9. msgsnd(msg_id,msg_mbuf,sizeof("message test"),IPC_NOWAIT);  
  10. msgrcv(msg_id,msg_mbuf,10,10,msg_rflags);  
  11. (*msg_info).msg_perm.uid=8;  
  12. (*msg_info).msg_perm.gid=8;  
  13. (*msg_info).msg_qbytes=12345;  
  14. msgctl(msg_id,IPC_SET,msg_info);  

上面代码里面msg_rflags=IPC_NOWAIT | MSG_NOERROR,msgrcv的第一个10代表接受信息大小,第二个时则是mtype,上面已经说过,只接受队列id里面到mtype相符的消息。msgctl则是对消息队列到内核管理的数据结构进行操作,具体可以man msgctl.

 

信号量可以理解成系统资源计数器,主要用来实现对临界资源到控制,如P,V操作。

基本函数如下:semget(key,int nsem,flag); 该函数创建信号量集合,nsem代表信号量个数。

semop(semid,*sops,nsops)对信号量进行操作,

[c-sharp]  view plain copy
  1. struct sembuf {  
  2.         unsigned short  sem_num;        /* semaphore index in array */  
  3.         short           sem_op;         /* semaphore operation */  
  4.         short           sem_flg;        /* operation flags */  
  5. };  

上述结构体是semop的sops参数,sem_num是要处理到信号量编号,sem_op有三种形式,+1,-1,0,+1把信号量加上一个值,该值是semop到第三个参数nsops,-1是减值,0将该进程设置成睡眠状态,直到信号量值为0.

简单例子struct sembuf sops={0,+1,IPC_WAIT};semop(semid,&sops,1)

semctl是对信号量进行操作。信号量还有一个union semun,它用在semctl函数里面,基本上跟消息队列一样。

共享内存是最直接的IPC方式,多个进程按照一定到方式对这段内存进行操作,就像操作自己申请的内存一样。

shmget(key,size,flags),申请一个共享内存,返回共享内存表示符,shmid

*shmget(shmid,*shmaddr,shmflg)进程获得该内存,如果shmaddr为空,则系统会自动查找未映射到区域,该函数返回内存地址

shmdt(*shmaddr)删除共享内存,它不是真正删除共享内存,只是给内核一个标示,当没有进程用到该共享内存时候,内核才会把它删掉。

shmctl(shmid,cmd,shmid_ds),大致跟消息队列函数一样,参考man手册

 

通过上面,可以看到消息队列,信号量,共享内存用到到函数格式都差不多,如*get(),*ctl之类,值得注意到是,无论你是创建消息队列,信号量集合还是共享内存,都会用到key,这个key在前面讲过到ftok函数生成。

signal用来异步控制进程的,可以用kill -l列出系统到信号,当然大部分信号到默认操作是空操作或者终止进程,你可以用signal()函数来绑定信号和你要实现的功能,如

singal(sig_num,handler),sig_num是你到信号值,如SIGSTOP,handler是函数指针,就是说当sig_num发生时候,执行handler指向的函数。

如先定义handler(sig_num){.....},然后signal(SIGSTOP,handler);这样,当发生该信号时候,就执行handler函数。

可以通过kill(pid,sig)来向pid进程发送sig信号,当pid为0时,向所有进程发送sig信号。

也可以raise(sig)想当前进程发送信号。

 

具体的函数参数介绍和用法可参考man 手册。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值