进程间通信的几种方法

很久以前学的进程通信,今天根据自己的理解将其分享出来。
1.管道:
是一种最简单的IPC机制,由

#include<unsitd.h>
pipe(int filedes[2]);  函数创建:
调用pipe函数在内核中申请开辟一块缓冲区(管道),用于通信,有一个写端和一个读端

这里写图片描述

这里写图片描述
这里写图片描述

这里写图片描述

简单的程序:
//打开管道,写入

#include<stdio.h>
#include<fcntl.h>
#include<stdlib.h>

int main()
{
     int fd;
     int count  = 5;
     int len;
     pid_t pid  = 0;
     char *path = "/home/gq/myfifo";
     fd = open(path,O_WRONLY);
     if(fd == -1)
     {
          perror("open myfifo");
          return 1;
     }
     while(count--){
          len = write(fd,"hello",6);
          printf("write return len %d\n",len); 
          sleep(1);
     }
     close(fd);
     return 0;
}
//从管道中读东西,只有当管道的读端和写端都打开的时候,管道才是通的,才能执行
int main()
{
     int fd;
     char buff[BUFSIZ];
     int len;
     pid_t pid  = 0;
     char *path = "/home/gq/myfifo";
     fd = open(path,O_RDONLY);
     if(fd == -1)
     {
          perror("open myfifo");
          return 1;
     }
     //while(1);
     while(1)
     {
          len = read(fd,buff,BUFSIZ);
          if(len>0)
           printf("%s\n",buff);
     }
 close(fd);
 return 0;
}
//如果是一个写,多个读,则多个的进程是随机的。

2.共享内存:

#include<sys/shm.h>

1>.为了在不同的进程中访问到相同的内存空间,首先获得唯一的key值。

  #define  PRJ_SHM_ID  'a'
  #define  PRJ_SEM_ID  'b'
  key_t  shmkey = ftok("/home", PRJ_SHM_ID);
  key_t  semkey = ftok("/home", PRJ_SEM_ID);

2>.向内存申请共享内存:

  int shmid = shmget(shmkey,10,SHM_W|SHM_R|IPC_CREAT);
  if(shmid < 0)  perrno("shmget"); return 1;

3>.获取指向共享内存的指针

    char *shmptr;
    shmptr = (char *)shmat(shmid,0,0);
    if(shmptr == NULL)
    {
       perror("shmat");
       return 1;
    }

4>.可以直接使用指针对内存进行读写操作。

 /*两种输入*/
 int i;
 while(1){
     char *p = shmptr;
     for(i=0;i<128;i++){
     //*p++ = '0' + i%10;
     *p++ = 'a' + i%26;
     usleep(1000);
     }
     }
/* 上面一种可能会造成打印的乱码*/
    strncpy(shmptr,"hello",6);
    printf("%s\n",shmptr);

6>.删除所创建的共享内存

 smctl(semid, IPC_RMID, NULL);

3.信号量signal:
这里写图片描述

#include<sys/sem.h>

1>.创建key值,可参考共享内存。
2>.在内核中创建信号量:

 int semid = semget(key, 1, IPC_CREAT);
 if(semid < 0)  perrno("semget"); return 1;

3>.设置信号量值

semctl(semid,0,SETVAL,1);

4>.查看并修改信号量的值

 struct sembuf sem1_wait = {0,-1,SEM_UNDO};
 struct sembuf sem1_wakeup = {0,1,SEM_UNDO};

把信号量值由1变为0
semop(semid,sem1_lock,1);
如果发现信号量是1,则变为0,马上退出。如果发现信号量是0,则阻塞,直到有人把0变成1,才会获得。
把信号量值由0变到1

 semop(semid, sem1_unlock, 1);

5>. 如果信号量不再使用了,可以删除

semctl(semid, IPC_RMID, NULL);

4.消息队列:

#include <sys/msg.h>
struct my_msg_st{
    long int msg_type;
    char some_text[BUFSIZ];
}; 

int msgid;

msgid = msgget(key_t key, int msgflg);
struct my_msg_st  some_data;

while(1){
    int msgrcv(int msgid, &some_data , BUFSIZ, 'a' ,0);

    printf("%d,%s\n",some_data.msg_type, some_data.some_text);

}

while(1){
    some_data.msg_type = 'a';
    strcpy(some_data.some_text, "hello");

    int msgsnd(msgid, &some_data, 6, 0);

}
int msgctl();

msgrcv, msgsnd的第五个参数依然是是控制函数行为的标志,取值可以是:
0,表示忽略;

IPC_NOWAIT,如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数
的进程。如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件的
消息为止。如果一个client 正在等待消息的时候队列被删除,EIDRM 就会被返回。如果进
程在阻塞等待过程中收到了系统的中断信号,EINTR 就会被返回。

MSG_NOERROR,如果函数取得的消息长度大于msgsz,将只返回msgsz 长度的信息,
剩下的部分被丢弃了。如果不指定这个参数,E2BIG 将被返回,而消息则留在队列中不被取出。

当消息从队列内取出后,相应的消息就从队列中删除了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值