信号量相关函数原型
获得一个信号量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联合体
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) */ };
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 */ };
下列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成员设置信号量集合中单个信号的值
自动执行信号量集合上的操作数组
#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结构体
struct sembuf { unsigned short sem_num; /* semaphore number */ short sem_op; /* semaphore operation */ short sem_flg; /* operation flags */ }
测试代码:
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 "); 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 "); 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 "); 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 "); 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 "); 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(" %d - finished ", 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(" %d - finished ", getpid()); 24 return 0; 25 }
运行方法:
./a.out 0 &./a.out