你的位置:首页 > 操作系统

[操作系统]Linux 进程间通信

Linux下的进程间通信-详解 - bitbit - 博客园

Linux下的进程间通信-详解详细的讲述进程间通信在这里绝对是不可能的事情,而且笔者很难有信心说自己对这一部分内容的认识达到了什么样的地步,所以在这...

Linux进程间通信总结 - 渣码农 - 博客园

Linux进程间通信总结 1. 管道 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: (1)管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要...

Linux进程间的通信方式和原理 - 刘广辉 - 博客园

Linux进程间的通信方式和原理 进程的概念 进程是操作系统的概念,每当我们执行一个程序时,对于操作系统来讲就...

深刻理解Linux进程间通信(IPC)

一个大型的应用系统,往往需要众多进程协作,进程(Linux进程概念见附1)间通信的重要性显而易见。本系列文章阐述了Linux环境下的几种主要进程间通信手段...

Linux下的进程间通信-详解 - xqhrs232的专栏 - CSDN博客

原文地址::https://.blogs./skyofbitbit/p/3651750.html 相关文章 1、Linux下进程通信的八种方法---https://.blogs./sooner/archive/...

Linux进程间通信方式 - godleading的专栏 - CSDN博客

由于基于fork机制,所以管道只能用于父进程和子进程之间,或者拥有相同祖先的两个子进程之间 (有亲缘关系的进程之间)。为了解决这一问题,Linux提供了FIF...

Linux---进程间通信-管道与两个命名管道实现进程双向通...-CSDN博客

在Linux系统中,有时候需要多个进程之间相互协作,共同完成某项任务,进程之间或线程之间有时候需要传递信息,有时候需要同步协调彼此工作,则就会出现进程...

Linux进程间通信之共享内存 - xcywt - 博客园

Linux进程间通信之共享内存 一,共享内存 内核管理一片物理内存,允许不同的进程同时映射,多个进程可以映射同一块内存,被多个进程同时映射的物理内存,即...

linux 进程间通信之pipe - Arlenmbx - 博客园

linux 进程间通信之pipe 在实际开发过程中,程序员必须让拥有依赖关系的进程集协调,这样才能达到进程的共同...

转:linux进程间通信的几种机制的比较及适用场合 - 天天向..._博客园

# 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。# 有名管...

Linux进程间通信的基本原理、通信方式及其同步方式的理..._CSDN博客

标签: Linux IPC 进程间通信 个人分类: Linux ***基本原理***:通常情况下,程序只能访问自身的数据,和其它进程没有沟通,每个进程都是一个单独存在的个...

Linux进程间通信的研究与实现毕业论文_百度文库

nbsp;评分:5/5nbsp;70页

Linux进程间通信的研究与实现毕业论文 - 本科学生毕业论文(设计) 题目(中文): (英姓学院文): 名号 (系) Linux 进程间通信的研究与实现 The researc...

Linux 进程间通信(一) - cococo点点 - 博客园

Linux 进程间通信进程是一个独立的资源分配单位,不同进程之间的资源是相互独立的,没有关联,不能在一个进程中直接访问另一个进程中的资源。但是,进程不...

Linux 进程间通信系列之 信号 - mingfeng002 - 博客园

信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;Linux除了支持Unix早期信号语义函数s...

Linux内核解析:进程间通信:管道 - 笨拙的菜鸟 - 博客园

管道是第一个广泛应用的进程间通信手段。日常在终端执行shell命令时,会大量用到管道。但管道的缺陷在于只能在有亲缘关系(有共同的祖先)的进程之间使用...

Linux 进程间通信(二) 管道 - cococo点点 - 博客园

主要用于父进程与子进程之间,或者两个兄弟进程之间。在linux系统中可以通过系统调用建立起一个单向的通信管道,且这种关系只能由父进程来建立。因此,每...

Linux进程间通信的几种方式总结--linux内核剖析(七) - ya..._博客园

有些进程希望全然控制还有一个进程的执行(如Debug进程),此时控制进程希望能够拦截还有一个进程的全部陷入和异常,并能够及时知道它的状态改变。 Linux ...

Linux进程间通信——使用信号 - jackjing - 博客园

sa_mask的值通常是通过使用信号集函数来设置的,关于信号集函数,我将会在我的下一篇文章——Linux进程间通信——信号集函数,详细讲述。 sa_flags,通常...

Linux进程间通信-信号 - 迪米特 - 博客园

Linux进程间通信-信号 1.什么是信号信号是Linux系统响应某些条件而产生的一个事件,接收到该信号的进程会执行相应的操作。 2.信号的产生1)由硬件产生,...“中国瀑乡 秀美安顺” 推荐会在深举行桂林有哪些最值得游玩的地方?桂林有哪些民间活动?七成大学生喜欢自由行 穷游一次花费不到四千英国工人中千万 玩转地球一圈行李超重怎么办?飞机行李超重怎么办 行李超重收费多少?秋天旅游景点推荐 秋天旅游好去处 秋天旅游去哪里推荐北京出发去埃塞俄比亚旅游 北京出发去埃塞俄比亚旅游 北京出发去埃塞俄比亚旅游 北京出发去埃塞俄比亚旅游 北京出发去埃塞俄比亚旅游 北京出发去埃塞俄比亚旅游 北京出发去爱尔兰旅游 北京出发去爱尔兰旅游 北京出发去爱尔兰旅游 北京出发去爱尔兰旅游 北京出发去爱尔兰旅游 北京出发去爱尔兰旅游 北京出发去爱沙尼亚旅游 北京出发去爱沙尼亚旅游 北京出发去爱沙尼亚旅游 北京出发去爱沙尼亚旅游 北京出发去爱沙尼亚旅游 北京出发去爱沙尼亚旅游 北京出发去安道尔旅游 北京出发去安道尔旅游 北京出发去安道尔旅游 北京出发去安道尔旅游 北京出发去安道尔旅游 北京出发去安道尔旅游

 1,

   进程通信:在用户空间实现通信时不可能的,通过linux内核通信

   线程间通信: 可以在用户空间实现,可通过全局变量通信

2,通信方式

   管道通信:无名管道,有名管道(文件系统中有名)

   信号通信:信号(通知)通信包括:信号的发送,信号的接受和信号的处理

 

      IPC通信:共享内存,消息队列,和信号灯

 

   以上是的单机模式下的进程通信(只有一个linux内核)

    

   Socket通信:存在于一个网络中两个进程间的通信(两个LINUX内核)

3,思路:  每种通信方式都是基于文件IO 的思想

    open 

    read

    write

    close

__________________________________________________________________________________________________

二:无名管道

    内核的管道是由队列实现(入队和出队)

    在文件IO中创建文件是由open 函数来实现,但它只能创建普通文件,管道文件需要用pipe函数来创建

      

    int  pipe (int fd[2]);    创建管道,微系统调用

    参数: 就是得到的 文件描述符。可见有两个文件 描述符:fd[0],fd[1]; 管道有一个读端fd[0] 和一个写端fd[1] ,不能改变

    返回值: 成功是0,出错时-1;

    

    注意:

      1)管道是创建在内存中的,进程结束,空间释放,管道就不存在了。

      2)管道中的东西,读完就删除了

      3)如果管道中没有东西可读,就会读阻塞。

      4)无名管道不能实现非父子进程(只能是内核中的同一管道)

#include "unistd.h"#include "stdio.h"#include "stdlib.h"int main(){ int fd[2]; int ret; char write_buf[] = "hello linux"; char read_buf[128] = {0}; ret = pipe(fd); if(ret <0) {  printf("creat process failure\n");  return -1; }  printf("creat process success ,fd[0]=%d,fd[1]=%d\n",fd[0],fd[1]);  write(fd[1],write_buf,sizeof(write_buf));  read(fd[0],read_buf,128);  printf("read:%s\n",read_buf); close(fd[0]); close(fd[1]); return 0;} 结果:creat process success ,fd[0]=3,fd[1]=4read:hello linux
pipe的简单用法

 

父子进程:fork();

pid = fork();

if (pid>0)   {};    父进程

if (pid ==0)  {};   子进程

    1)在父进程中,fork返回新创建子进程的进程ID;
    2)在子进程中,fork返回0;
    3)如果出现错误,fork返回一个负值;

getpid();获取当前进程ID

getppid();获取当前进程的父进程ID

 三:有名管道

    通过管道实现无亲缘关系进程间通信,

    1,创建这个文件节点,不可以通过open 函数,open 函数只能创建普通文件,不能创建特殊文件(管道 -mkdifo ,套接字 -socket ,字符设备文件 -mknod ,块设备文件 -mknod , 符号链接文件 -ln -s, 目录文件 mkdir )

    2,管道文件只有inode 号,不占磁盘块空间,和套接字、字符设备文件、块设备文件一样。 普通文件和符号链接文件及目录文件,不仅有inode 号,还占磁盘空间。

 

    3,mkfifo  用来创建管道文件的节点,没有在内核中创建管道

          只有通过open函数打开这个文件是才会在内核空间创建管道

 

    mkfifo

    int  mkfifo (const char *filename,mode_t mode);   创建管道文件

    参数:管道文件名,权限(仍与umask有关),

    返回值:创建成功返回0,失败返回-1

    

四:信号通信

  信号通信,其实就是内核向用户空间进程发送信号,只有内核才能发送信号,用户空间进程不能发送信号。

  

  信号通信的框架:

  信号的发送:(发送信号进程)  kill  raise  alarm

  信号的处理:(接受信号进程)  pause()   sleep(睡眠)   while(1)

  信号的发送:(发送信号进程)  signal

  1,信号的发送()

    kill :

      头文件:#include  <signal.h>

          #inlcude  <sys/types.h>

      函数:  int kill (pid_t pid,int sig);

      参数:pid : 1,正数:要接受信号的进程的进程号    2,0:信号被发送到所有和PID进程在同一个进程组的进程      3,-1:信号发给所有的进程表中的进程(除了进程号最大的进程外)

         sig :  信号

      返回值:成功 :0;    出错:-1;

      此时kill为函数,kill命令为结束进程 ,kill函数可以实现命令功能

  

    raise :  发信号给自己  ==  kill (getpid(),sig)

  •       头文件:#include  <signal.h>

             #include <sys/types.h>

  •       函数: int raise (int sig);
  •       参数:sig : 信号
  •       返回值:成功 :0;    出错:-1;

    alarm   :  闹钟信号    定时,只能发送给当前进程

  •        头文件:#include "unsitd.h"
  •        函数:    unsigned int alarm  (insigned int seconds);
  •        参数:    seconds   指定秒数
  •        返回值: 成功:如果调用alarm()前,进程已经设置了闹钟时间,则返回上一个闹钟的剩余时间,负责返回0 ;          出错:-1;

 

    2,信号的接收

      要想使接收到进程的能接收到信号,进程不能结束;

  •       sleep;
  •       pause:    进程状态为 S(睡眠状态),     与sleep 不同的是,sleep 可以是进程睡眠一段时间,而pause 如果不唤醒,它可以一直睡眠;
  •       while(1);

      

      pause:

  •         头文件:#inlclude "unistd.h"
  •         函数: int  pause (void);
  •         返回值: 成功    :  0  ;出错  :  -1;

    3,信号的处理

     (1)进程的默认处理方式(内核为用户进程设置的默认处理方式)    

  •        忽略
  •        终止进程  
  •        暂停

     (2)自己的处理方式

          自己处理信号的方法告诉内核,这样你的进程收到了这个信号就会采用自己的处理方式

         signal

          头文件: #include "signal.h"

          函数:      void  (*signal (int signum, void (*handler) (int))) (int);

          参数:

              signum  :   指定信号

              hangler:     

                    SIG_IGN   :     忽略该信号

                    SIG_DFL   :  采用系统默认方式处理信号 (终止)

                    自定义的信号处理函数指针

          返回值: 成功  :设置之前的信号处理方式 ;               出错 :   -1   ;

 

                                    自我感觉就像是中断???

 1 #include "sys/types.h" 2 #include "signal.h" 3 #include "stdlib.h" 4  5 void myfun() 6 { 7 int i; 8 for(i=0;i<10;i++) 9  printf("second , i=%d\n",i);10  return;11 12 }13 int main()14 {15  int i;16  i=0;17  signal(14,myfun);18  printf("alarm before\n");19  alarm(4);20  printf("alarm after\n");21 22  while(i<10)23   {24   i++;25   sleep(1);26   printf("main,i=%d\n",i);27 28   }29  return 0;30 }31 ~                            32 33 结果:34 alarm before35 alarm after36 main,i=137 main,i=238 main,i=339 second , i=040 second , i=141 second , i=242 second , i=343 second , i=444 second , i=545 second , i=646 second , i=747 second , i=848 second , i=949 main,i=450 main,i=551 main,i=652 main,i=753 main,i=854 main,i=955 main,i=1056 
信号处理

 

 

 

 

IPC通信————》IPC对象 {共享内存,消息队列,信号灯};

文件IOIPC
open

Msg_get     打开或创建消息队列

Shm_get    创建共享内存

Sem_get    创建信号灯

read

write

msgsnd   msgrecv    (读   写)

shmat      shmdt

semop

close

msgctrl

shmctrl

semctrl

 

 

五,共享内存

              共享内存就是一块缓存,类似于用户空间的数组,或malloc函数分配的空间一样

               1,Shm_get    打开或创建共享内存

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

          #include <sys/ipc.h>

          #include <sys/shm.h>

      函数:   int  shmget  (key_t key, int size ,int shmflg);

      参数: key  :    IPC_PRIVATE  或 ftok  的返回值,,,,(在使用返回值时,需要加宏)(     shmid = shmget (key,128,IPC_CREAT | 0777);     )

          size :    共享内存的大小

          shmflg:   同open 函数的权限位,也可用8进制表示法

      返回值:        成功   共享内存标识符——ID——文件描述符 ;      出错   :  -1   ;

 

      查看IPC对象  :  ipcs -m(查看内核空间共享内存对象)    -q (消息队列)    -s (信号灯)

      删除IPC对象  :       ipcrm  -m   id

      返回值: 共享内存段标识符     IPC 的ID 号

 1 #include "signal.h" 2 #include "unistd.h" 3 #include "stdio.h" 4 #include "stdlib.h" 5 #include "sys/types.h" 6 #include "sys/shm.h" 7  8 int main() 9 {10  int shmid;11 int pid;12 13  pid = ftok("./home/xiaozhao/2.c",'a');14  shmid = shmget(pid,128,IPC_CREAT | 0777);15 16  if(shmid<0)17   {18   printf("creat share memory failure\n");19   return -1;20   }21 22   printf("craet share meory sucess\n"); //创建共享内存23   system("ipcs -m");24   return 0;25 26 }27 28 29 30 31 结果:32 craet share meory sucess33 34 ------------ 共享内存段 --------------35 键  shmid  拥有者 权限  字节  连接数 状态  36 0x00000000 1179648 xiaozhao 600  524288  2   目标  37 0x00000000 393217  xiaozhao 600  524288  2   目标  38 0x00000000 425986  xiaozhao 600  524288  2   目标  39 0x00000000 688131  xiaozhao 600  524288  2   目标  40 0x00000000 720900  xiaozhao 600  16777216 2      41 0x00000000 819205  xiaozhao 600  524288  2   目标  42 0x00000000 1081350 xiaozhao 600  524288  2   目标  43 0x00000000 950279  xiaozhao 600  67108864 2   目标  44 0x00000000 1212424 xiaozhao 600  1048576 2   目标  45 0x00000000 1376265 xiaozhao 600  524288  2   目标  46 0x00000000 1736714 root  777  128  0      47 0xffffffff 1769483 root  777  128  0  
key 的不同用法

 

                  {              

          key   的区别

                 1)  使用宏创建的key ,,,始终为0

          2)  ftok   :  创建key 的值

              char ftok (const  char *path ,char key)

              参数: 第一个:  文件路径和文件名  ;    第二个 : 一个字符;

              返回值: 正确返回一个key的值,  错误返回-1;

 

            IPC_PRIVATE  操作时,共享内存的key 值是0;所以使用 ftok 开创建KEY值。  只要KEY 的值是一样的,用户空间的进程通过这个函数打开,则会对内核的同一个IPC对象操作

      }

      

      3,shmat     将共享内存映射到用户空间中

          为了方便用户空间对共享内存的操作,使用地址映射的方式

          

          void *shmat (int shmit ,const void *shmaddr , int shmflg);

            参数: shmat :    ID 号

                shmaddr:   映射到的地址,NULL为系统自动完成的映射

                shmflg:    SHM_RDONLY  共享内存只读  ;    默认是0 , 表示共享内存可读写  ;

            返回值: 成功  :  映射后的地址  ;        出错  : NULL;

      

                 shmdt     :   将用户空间进程里的地址映射删除。

            int shmdt (const void *shmaddr);

            参数: shmaddr 共享内存映射后的地址;(就是映射后的返回值)

            返回值: 成功  :  0  ;     失败    :   -1  ;

    

      共享内存的特点: 

        1) 共享内存创建之后,一直存在于内核之中,直到被删除或系统关闭

        2)共享内存和管道不一样,读取后,内容仍在其共享内存中。

 

         shmctl :   删除共享内存对象

          函数: int shmctl (int shmid , int cmd , struct shmid_ds *buf);

          参数: shmid :  要操作的共享内存标识符

              cmd :      IPC_STAT    (获取对象属性)       —————— 实现了  ipcs  -m

                    IPC_SET    (设置对象属性)

                    IPC_RMID    (删除对象) ——————实现了  ipcrm -m

              buf   :          指定IPC_STAT/IPC_SET  时用以保存/设置属性

          返回值:   成功  :0  ;   出错   :  -1;

                  

          当删除共享内存时,不需要第三个参数,可以设置为NULL

     

 1 include "signal.h" 2 #include "unistd.h" 3 #include "stdio.h" 4 #include "stdlib.h" 5 #include "sys/types.h" 6 #include "sys/shm.h" 7  8 int main() 9 {10  int shmid;11  char *p;12 13  shmid = shmget(IPC_PRIVATE,128,0777);14 15  if(shmid<0)16   {17   printf("creat share memory failure\n");18   return -1;19   }20 21   printf("craet share meory sucess\n"); //创建共享内存22   system("ipcs -m");23 24   p = (char *)shmat(shmid,NULL,0);  //映射到用户空间25   if(p == NULL)26    {27    printf("shmat function failure\n");28    return -2;29    }30    printf("shmat function sucess\n");31 32     //写内容,从键盘输入33   fgets(p,128,stdin);34 35     //读36   printf("read : p=%s\n",p);37  return 0;38 39 }40 41 42 43 结果:44 craet share meory sucess45 46 ------------ 共享内存段 --------------47 键  shmid  拥有者 权限  字节  连接数 状态  48 0x00000000 1179648 xiaozhao 600  524288  2   目标  49 0x00000000 393217  xiaozhao 600  524288  2   目标  50 0x00000000 425986  xiaozhao 600  524288  2   目标  51 0x00000000 688131  xiaozhao 600  524288  2   目标  52 0x00000000 720900  xiaozhao 600  16777216 2      53 0x00000000 819205  xiaozhao 600  524288  2   目标  54 0x00000000 1081350 xiaozhao 600  524288  2   目标  55 0x00000000 950279  xiaozhao 600  67108864 2   目标  56 0x00000000 1212424 xiaozhao 600  1048576 2   目标  57 0x00000000 1376265 xiaozhao 600  524288  2   目标  58 0x00000000 1736714 root  777  128  0      59 60 shmat function sucess61 1231few62 read : p=1231few
共享内存简单代码

 

 1 #include "signal.h" 2 #include "unistd.h" 3 #include "stdio.h" 4 #include "stdlib.h" 5 #include "sys/types.h" 6 #include "sys/shm.h" 7 #include "string.h" 8  9 void fun ( int signum)10 {11 return ;12 13 }14 int main()15 {16  int shmid;17 int key,pid;18 char *p;19 20  key=ftok("/home/xiaozhao/2.c",'a'); //获取key值 ,在单向通讯中,可以直接使用宏21  if(key<0)22   {23   printf("creat key failure\n");24   return -2;25   }26   printf("creat key sucess\n");27 28 29  shmid = shmget(pid,128,IPC_CREAT | 0777); // 创建共享内存30  if(shmid<0)31   {32   printf("creat share memory failure\n");33   return -1;34   }35    printf("share meory sucess\n");36 37  pid=fork();38   if(pid>0)39   {40    signal(SIGUSR2,fun);41   p = (char *)shmat(shmid,NULL,0); //父进程映射42   if(p==NULL)43     {44     printf("parent process:shmat function failuer\n");45     return -3;46     }47   while(1)48   {49   printf("parent process start write share memory:\n");50   fgets(p,128,stdin);51   kill(pid,SIGUSR1); //child process read data52    pause();53   }54   }55 56 57   if(pid==0)58   {59    signal(SIGUSR1,fun);60   p = (char *)shmat(shmid,NULL,0);61   while(1)62   {63    pause();64   printf("share memory data:%s",p);65    kill(getppid(),SIGUSR2);66   }67   }68 69   shmdt(p);70   shmctl(shmid,IPC_RMID,NULL);71   system("ipcs -m");72 73 74   return 0;75 76 }77 78 79 结果:80 creat key sucess81 share meory sucess82 parent process start write share memory:83 12384 share memory data:12385 parent process start write share memory:86 12387 share memory data:12388 parent process start write share memory:
父子进程单向通信

 

     fork() 放在 Shmget  之后,可以保证父子进程在同一共享内存中进行。

 

     六,消息队列

      管道为顺序队列,而消息队列为链式队列

      1,msgget     打开创建消息队列

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

             #include <sys/ipc.h>

             #include <sys/msg,h>

         函数: int  msgget (key_t key, int flag);

         参数: key  :   和消息队列关联的KEY值

             flag  :   消息队列的访问权限

         返回值: 成功  :消息队列ID  ;   出错  : -1;

 

      2,msgctl    删除消息队列

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

 

             #include <sys/ipc.h>

 

             #include <sys/msg,h>

         函数: int msgctl (int msgqid, int cmd,struct msqid_ds *buf);

         参数: msqid   :   消息队列ID

            cmd   :      IPC_STAT  :   读取消息队列的属性,并将其保存在BUF指向的缓存中

                  IPC_SET    :  设置消息队列的属性,这个参数取自BUF

                 IPC_RMID :  从系统中删除消息队列

            buf     :      消息队列缓存区

          返回值:  成功  0    ;  出错  -1;

 

          当删除消息队列时,不需要第三个参数,可以设置为NULL

  

      3,msgsnd    发送消息

        函数:  int msgsnd (int msqid, const void *msgp,size_t size,int flag);

        参数:  msqid   :    消息队列ID

             msgp   :     指向消息队的指针。常用消息结构msgbuf 如下:

                               struct  msgbuf

                                  {

                                   long mtype;        //消息类型

                                   char  mtext[N];   // 消息正文

                                  }

            size    :      发送消息正文的字节数

            flag    :       IPC_NOWAIT        消息没有发送完成函数也会立即返回

                 0                             直到消息发送完成才返回

            返回值:   成功   0  ;   出错    -1;

      4,msgrcv    接收消息

          函数: int  msgrcv (int msgid,   void *msgp ,  size_t size ,   long msgtype ,   int flag);

          参数:   msqid  :    消息队列 ID 

              msgp :     接收消息的缓冲区

              size   :      要接收的消息的字节数

              msgtype:       0     接收消息队列中的第一个消息

                    大于0     接收消息队列中第一个类型为 msgtyp  的消息

                    小于0     接收消息队列中类型值不大于msgtyp 的绝对值且类型又最小的消息

              flag     :      0       若无消息函数会一直阻塞

                   IPC_NOWAIT       若没有消息,进程会立即返回ENOMSG

          返回值: 成功 :接收到的消息长度    ;    出错    -1;     

 

        读就是删除,写就是插入。

 

 

 1 #include "sys/types.h" 2 #include "sys/msg.h" 3 #include "signal.h" 4 #include "unistd.h" 5 #include "stdio.h" 6 #include "stdlib.h" 7 #include "string.h" 8 struct msgbuf 9 {10 long type;11 char buf[124];12 };13 14 int main()15 {16 int msgid;17 struct msgbuf sendbuf,readbuf;18  msgid = msgget(IPC_PRIVATE,0777);19   if(msgid<0)20   {21   printf ("creat message queue failure\n");22   return -1;23   }24   printf("creat message queue sucess , msgid=%d\n",msgid);25 26   system("ipcs -q");27     // init sengbuf28   sendbuf.type=100;29   printf("please input message :\n");30   fgets(sendbuf.buf,124,stdin);31   msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.buf),0);32 33   memset(readbuf.buf,0,124);34   msgrcv(msgid,(void *)&readbuf,124,100,0);35   printf("read :%s\n",readbuf.buf);36 37 //  msgctl(msgid,IPC_RMID,NULL);38   system("ipcs -q");39 40 41 42 return 0;43 44 }45 46 结果:47 creat message queue sucess , msgid=9830548 49 --------- 消息队列 -----------50 键  msqid  拥有者 权限  已用字节数 消息  51 0x00000000 65536  root  777  0   0   52 0x00000000 98305  root  777  0   0   53 54 please input message :55 1232131356 read :1232131357 58 59 --------- 消息队列 -----------60 键  msqid  拥有者 权限  已用字节数 消息  61 0x00000000 65536  root  777  0   0   62 0x00000000 98305  root  777  0   0
消息队列简单读取

 

 1 write: 2 #include "sys/types.h" 3 #include "sys/msg.h" 4 #include "signal.h" 5 #include "unistd.h" 6 #include "stdio.h" 7 #include "stdlib.h" 8 #include "string.h" 9 struct msgbuf 10 { 11 long type; 12 char buf[124]; 13 }; 14  15 int main() 16 { 17 int msgid; 18 int key; 19   struct msgbuf sendbuf; 20   key=ftok("/home/xiaozhao/b.c",'a'); 21  if(key<0) 22  { printf(" creat key failure\n");  23   return -2;} 24   printf("creat key sucess\n");  25   msgid = msgget(key, IPC_CREAT | 0777); 26  if(msgid<0) 27  { 28   printf ("creat message queue failure\n"); 29  return -1;  30  } 31   printf("creat message queue sucess , msgid=%d\n",msgid); 32  33  system("ipcs -q"); 34   // init sengbuf  35  sendbuf.type=100; 36 while(1) 37 { 38  printf("please input message :\n"); 39  fgets(sendbuf.buf,124,stdin); 40  msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.buf),0); 41  42 //  memset(readbuf.buf,0,124); 43 // msgrcv(msgid,(void *)&readbuf,124,100,0); 44 // printf("read :%s\n",readbuf.buf); 45 } 46  msgctl(msgid,IPC_RMID,NULL); 47  system("ipcs -q"); 48   return 0; 49 } 50  51  52  53  54 read: 55 #include "sys/types.h" 56 #include "sys/msg.h" 57 #include "signal.h" 58 #include "unistd.h" 59 #include "stdio.h" 60 #include "stdlib.h" 61 #include "string.h" 62 struct msgbuf 63 { 64 long type; 65 char buf[124]; 66 }; 67  68 int main() 69 { 70 int msgid; 71 int key; 72   struct msgbuf readbuf; 73   key=ftok("/home/xiaozhao/b.c",'a'); 74  if(key<0) 75  { printf(" creat key failure\n");  76   return -2;} 77 printf("creat key sucess\n");  78   msgid = msgget(key, IPC_CREAT | 0777); 79  if(msgid<0) 80  { 81   printf ("creat message queue failure\n"); 82  return -1;  83  } 84   printf("creat message queue sucess , msgid=%d\n",msgid); 85  86  system("ipcs -q"); 87   // init sengbuf  88 // sendbuf.type=100; 89 while(1) 90 { 91 // printf("please input message :\n"); 92 // fgets(sendbuf.buf,124,stdin); 93 // msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.buf),0); 94  95   memset(readbuf.buf,0,124); 96  msgrcv(msgid,(void *)&readbuf,124,100,0); 97  printf("read :%s\n",readbuf.buf); 98 } 99  msgctl(msgid,IPC_RMID,NULL);100  system("ipcs -q");101   return 0;102 }103 
消息队列单向通信

        消息队列双向通信必须保证收发数据类型不同,用父子进程可以实现

 

   七,信号灯 

        信号量的集合

 

    1,semget                 创建信号灯

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

                #include <sys/ipc.h>

                #include <sys.sem.h>

            函数: int semget (key_t key ,int nsems ,int semfig);

            参数: key :       和信号灯集关联的key 值

              nsems:        信号灯集合包含的信号灯数目

              semfig :     信号灯集的访问权限

            返回值: 成功 :  信号灯集ID    出错  :   -1

 

    2, semctl                    删除信号灯

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

                #inlcude <sys/ipc.h>

                #include <sys/sem.h>

            函数:   int  semctl ( int semid , int semnum , int cmd ,...union semun arg);

            参数:   semid   :    信号灯集ID

                  semnum   :    要修改的信号灯编号

                cmd     :      GETVAL   :    获取信号灯的值

                     SETVAL    :  设置信号灯的值

                     IPC_RMID :  从系统中删除信号灯集合

                 (删除时) 第四个参数可以NULL,也可以不写。 

             返回值 ;   成功  :0    ; 出错  -1

        

          设置信号灯时用到第四个参数(联合体)

          union  semun

            {

              int val;

                // SETVAL  :   设置信号灯的值

              struct semid_ds *buf;

                // IPC_STAT   (获取对象属性)

                //IPC_SET        (设置对象属性)

              unsigned short  *array ;    /* Array for GETALL,SETALL */

              struct seminfo   *_buf   ;   /*Buffer for IPC_INFO (Linux-specific) */

            };

    3,semop                信号灯P操作

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

                #inlcude <sys/ipc.h>

                #include <sys/sem.h>

            函数 ;   int  semop  (  int semid ,struct sembuf  *opsptr ,  size_t nops);

            参数 :   semid   :   信号灯集ID

               struct sembuf {

                 short  sem_num;    //要操作的信号灯的编号

                 short  sem_op ;      //   0  :  等待 , 直到信号灯的值变成0    

                           1  :  释放资源,V操作

                            -1   :  分配资源,P操作

                   short   sem_fig ;     //    0(阻塞),IPC_NOWAIT(非阻塞), SEM_UNDO()

                  }