欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

Linux 进程间通信

程序员文章站 2022-06-26 10:20:29
1, 进程通信:在用户空间实现通信时不可能的,通过linux内核通信 线程间通信: 可以在用户空间实现,可通过全局变量通信 2,通信方式 管道通信:无名管道,有名管道(文件系统中有名) 信号通信:信号(通知)通信包括:信号的发送,信号的接受和信号的处理 IPC通信:共享内存,消息队列,和信号灯 以上 ......

 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)无名管道不能实现非父子进程(只能是内核中的同一管道)

Linux  进程间通信
#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]=4
read: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   ;

 

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

Linux  进程间通信
 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 before
35 alarm after
36 main,i=1
37 main,i=2
38 main,i=3
39 second , i=0
40 second , i=1
41 second , i=2
42 second , i=3
43 second , i=4
44 second , i=5
45 second , i=6
46 second , i=7
47 second , i=8
48 second , i=9
49 main,i=4
50 main,i=5
51 main,i=6
52 main,i=7
53 main,i=8
54 main,i=9
55 main,i=10
56    
信号处理

 

 

 

 

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

文件io ipc
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 号

Linux  进程间通信
 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 sucess
33 
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

     

Linux  进程间通信
 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 sucess
45 
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 sucess
61 1231few
62 read : p=1231few
共享内存简单代码

 

Linux  进程间通信
 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 data
52            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 sucess
81 share meory sucess
82 parent process start write share memory:
83 123
84 share memory data:123
85 parent process start write share memory:
86 123
87 share memory data:123
88 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;     

 

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

 

 

Linux  进程间通信
 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 sengbuf
28         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=98305
48 
49 --------- 消息队列 -----------
50 键        msqid      拥有者  权限     已用字节数 消息      
51 0x00000000 65536      root       777        0            0           
52 0x00000000 98305      root       777        0            0           
53 
54 please input message :
55 12321313
56 read :12321313
57 
58 
59 --------- 消息队列 -----------
60 键        msqid      拥有者  权限     已用字节数 消息      
61 0x00000000 65536      root       777        0            0           
62 0x00000000 98305      root       777        0            0
消息队列简单读取

 

Linux  进程间通信
  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()

                  }