linux IPC的信号量

时间:2021-10-15 15:13:05

信号量相关函数原型

获得一个信号量ID

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semget(key_t key, int nsems, int semflg);
返回值:成功信号量ID,出错-1
key:函数ftok返回值或IPC_PRIVATE(适合用在有亲缘关系的进程中)
nsems:新的信号量集合中要创建的信号量个数,如果不是新创建的为0
semflg:  0取信号量集标识符,若不存在则函数会报错
      IPC_CREAT:当semflg&IPC_CREAT为真时,如果不存在与key值相等的信号量集,则创建。否则返回此信号量集的标识符。
      IPC_CREAT|IPC_EXCL:如果不存在与key值相等的信号量集,则创建。否则存在这样的信号集报错

 

对信号量的多种操作

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semctl(int semid, int semnum, int cmd, ...);
除了GETALL以外的所有命令,成功0失败-1
semid:信号量标识符
semnum:信号量集数组上的下标,表示某个信号量
cmd:下面有说明
arg:semnum联合体
linux IPC的信号量linux IPC的信号量
union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           };
union semun
linux IPC的信号量linux IPC的信号量
struct semid_ds {
               struct ipc_perm sem_perm;  /* Ownership and permissions */
               time_t          sem_otime; /* Last semop time */
               time_t          sem_ctime; /* Last change time */
               unsigned long   sem_nsems; /* No. of semaphores in set */
           };
struct semid_ds
linux IPC的信号量linux IPC的信号量
下列10种命令
IPC_STAT        对此集合取semid_ds结构,并存储在arg.buf指向的结构中 
IPC_SET          设置一个信号量集合的semid_ds结构中ipc_perm域的值,并从semun的buf中取出值
IPC_RMID       从内核中删除信号量集合  
GETALL           从信号量集合中获取所有信号量的值,并存到semun中的指针数组
GETNCNT        返回当前等待100%自远离用的进程个数
GETPID          返回最后执行semop的进程PID
GETVAL          返回信号量集合内单个信号量的值
GETZCNT         返回当前等待100%资源利用的进程个数
SETALL            与GETALL正好相反
SETVAL            用联合体中val成员设置信号量集合中单个信号的值
cmd指令

 

自动执行信号量集合上的操作数组

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semop(int semid, struct sembuf *sops, size_t nsops);
返回值:成功0出错-1
semid:信号量标识符
sops:是指向结构体数组的指针
nsops:操作结构体的数量,恒大于或等于1

sembuf结构体

linux IPC的信号量linux IPC的信号量
struct sembuf {
           unsigned short sem_num;  /* semaphore number */
           short          sem_op;   /* semaphore operation */
           short          sem_flg;  /* operation flags */
}
struct sembuf

 

测试代码:

  1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/ipc.h>
  4 #include <sys/sem.h>
  5 
  6 int semid = 0;
  7 
  8 union semun {
  9     int val;
 10     struct semid_ds *buf;
 11     unsigned short *arry;
 12 };
 13 
 14 int set_semvalue()
 15 {
 16     union semun sem_union;
 17 
 18     sem_union.val = 1;
 19     if(semctl(semid, 0, SETVAL, sem_union) == -1)
 20         return -1;
 21 
 22     return 0;
 23 }
 24 
 25 void del_semvalue()
 26 {
 27     union semun sem_union;
 28 
 29     if(semctl(semid, 0, IPC_RMID, sem_union) == -1)
 30         fprintf(stderr, "Failed to delete semaphore\n");
 31 }
 32 
 33 int P()
 34 {
 35     struct sembuf sem_b;
 36     sem_b.sem_num = 0;
 37     sem_b.sem_op = -1;
 38     sem_b.sem_flg = SEM_UNDO;
 39     if(semop(semid, &sem_b, 1) == -1)
 40     {
 41         fprintf(stderr, "P() failed\n");
 42         return -1;
 43     }
 44     return 0;
 45 }
 46 
 47 int V()
 48 {
 49     struct sembuf sem_b;
 50     sem_b.sem_num = 0;
 51     sem_b.sem_op = 1;
 52     sem_b.sem_flg = SEM_UNDO;
 53     if(semop(semid, &sem_b, 1) == -1)
 54     {
 55         fprintf(stderr, "V() failed\n");
 56         return -1;
 57     }
 58     returi 0;
 59 }
 60 
 61 int main(int argc, char *argv[])
 62 {
 63     char msg = 'X';
 64     int i=0;
 65 
 66     if(argc > 1 && !strcmp(argv[1], "0"))
 67     {
 68         /* first user sem */
 69         if(set_semvalue() == -1)
 70         {
 71             fprintf(stderr, "Failed to initialize semaphore\n");
 72             return -1;
 73         }
 74         msg = argv[1][0];
 75         sleep(2);
 76     }
 77 
 78     semid = semget((key_t)1234, 1, 0666|IPC_CREAT);
 79     if(semid == -1)
 80     {
 81         printf("semget error\n");
 82         return -1;
 83     }
 84     for(i=0;i<10;i++)
 85     {
 86         if(P() == -1)
 87             return -1;
 88         printf("%c", msg);
 89         fflush(stdout);
 90         sleep(rand()%3);
 91         printf("%c", msg);
 92         fflush(stdout);
 93         if(V() == -1)
 94             return -1;
 95         sleep(rand()%2);
 96     }
 97     sleep(5);
 98     printf("\n%d - finished\n", getpid());
 99 
100     if(argc > 1)
101         del_semvalue();
102 
103     return 0;
104 }

 第二个竞争了例子:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <sys/types.h>
 4 #include <unistd.h>
 5 
 6 int main(int argc, char *argv[])
 7 {
 8     char msg = 'X';
 9     int i =0; 
10     if(argc >1) 
11         msg = argv[1][0];
12 
13     for(i=0;i<10;i++)
14     {   
15         printf("%c", msg);
16         fflush(stdout);
17         sleep(rand()%3);
18         printf("%c", msg);
19         fflush(stdout);
20         sleep(rand()%2);
21     }   
22     sleep(10);
23     printf("\n%d - finished\n", getpid());
24     return 0;
25 }

 运行方法:

./a.out 0 &./a.out