博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
IPC——信号量
阅读量:7068 次
发布时间:2019-06-28

本文共 17474 字,大约阅读时间需要 58 分钟。

信号量作用

当多个进程/线程进行共享操作时,用于资源保护,以防止出现相互干扰的情况。再间简洁一点,信号量用于“资源的保护“。

进程信号量:实现的是进程所操作资源的保护。

线程信号量:实现的是线程所操作资源的保护。

疑问:资源保护,这个“资源”到底指的是谁?

:这个资源指的就是你操作的数据,保护的目的就是不要出现相互干扰,导致紊乱和错误数据的产生。

 

资源保护操作的种类

资源保护的操作分两种,一种叫互斥,另一个种叫同步。有些资源保护机制只能实现互斥,不能实现同步,比如。但是这里讲的信号量既能实现互斥,也能实现同步。

互斥

对于互斥操作来说,多进程共享操作时,多个进程间不关心谁先操作、谁后操作的先后顺序问题,它们只关心一件事,那就是我在操作时别人不能操作。互斥时,如果当前正在操作的进程,他的时间片到了,切换到了其他进程上,但是当该进程检测到上一个进程还没有操作完时,该进程在当前的时间片内会休眠,直到再次切换会上一个进程,将操作完成后再切换回来,此时才能进行操作。这跟上厕所时把门关起来是一样的,我在蹲坑时你不能蹲,你在蹲坑时我不能蹲,这就是互斥,至于蹲坑先后顺序并没有要求。

2018-9-23更新

想象一下这种场景,10个进程,每个进程都要访问临界区,CPU分配给进程的时间片是10ms。假设第一个进程进入临界区并加锁,10ms时间片到,进程还没有出临界区,锁还在第一个进程的手里。由于时间片到了,调度进程切换其他进程到CPU上执行,假设在第2ms的时候需要进入临界区,由于临界区的锁在第一个进程手中,于是当前进程阻塞。后面8个进程同样原因阻塞。有一个时刻CPU还会切换到第一个进程(第一个进程是由于时间片到了,被切换掉,但他还是就绪状态),第一个进程执行完毕后唤醒阻塞队列上其他进程。假设唤醒第二个进程,第二个进程拿锁顺利进入临界区,10ms没执行完,被切换掉了。但是此时就绪队列上只有第二个进程,于是第二个经常继续执行,执行完毕后唤醒第三个进程,依次类推

2018-9-23更新

同步

同步其实本身就包含了互斥,不过同步不仅仅只互斥,同步对于谁先操作、谁后操作的先后顺序有要求,比如规定A进程先写,然后是B进程写,然后是C进程写,绝对不能出现这操作顺序以外的顺序。所以所谓同步就是,多个共享操作时,进程必须要有统一操作的步调,按照一定的顺序来操作。

实现同步、互斥,其实就是加锁

这个很形象,我要操作我就上把锁,我上锁的过程中你就不能操作,直到我把锁打开了,你才能操作,你操作时也会加锁,加锁后我就不能操作了。所以说信号量就是一个加锁机制,通过加锁来实现同步和互斥。不管是进程还是线程,都存在同步和互斥的问题,同步和互斥的目的其实就是为了实现“资源”的保护,不要让数据(资源)出现紊乱。

疑问:信号量既然是一种加锁机制,为什么进程信号量会被归到了进程间通信里面呢?

资源保护时,某个进程的操作没有完全完成之前,别人是不能操作的,那么进程间必须相互知道对方的操作状态,必须会涉及到通信过程。所以信号量实现资源保护的本质就是,通过通信让各个进程了解到操作状态,然后查看自己能不能操作。

 

 

信号量的使用步骤

①进程调用semget函数创建新的信号量集合,或者获取已有的信号量集合。

②调用semctl函数给集合中的每个信号量设置初始值

③调用semop函数,对集合中的信号量进行pv操作

什么是pv操作?pv操作其实说白了就是加锁、解锁操作。

P操作(加锁):对信号量的值进行-1,如果信号量的值为0,p操作就会阻塞

V操作(解锁):对信号量的值进行+1,V操作不存在阻塞的问题

④调用semctl删除信号量集合

 

API

semget

原型

#include 
#include
#include
int semget(key_t key, int nsems, int semflg);

功能

根据key值创建新的、或者获取已有的信号量集合,并返回其标识符。

实现互斥时:集合中只需要一个信号量

实现同步时:集合中需要多个信号量 

参数

key:设置同消息队列和共享内存。一般都使用ftok获取key值。

nsems:指定集合中信号量的个数。

用于互斥时,数量都指定为1,因为只需要一个信号量。如果是

用于同步时,需要多个信号量(≥2)。

semflg:设置同消息队列和共享内存。一般都设置为0664|IPC_CREAT。

返回值

调用成功则返回信号量集合的标识符,失败则返回-1,并且errno被设置。

semctl

原型 

#include 
#include
#include
int semctl(int semid, int semnum, int cmd, ...);

功能

根据cmd的要求对集合中的各个信号量进行控制,...表示它是一个变参函数,如果第四个参数用不到的话,可以省略不写。

参数

semid:信号量标识符。通过标识符就能找到信号量集合。

semnum:集合中某个信号量的编号。信号量的编号为非负整数,而且是自动从0开始编号的。通过信号量编号就能找到集合中对应信号量,然后对这个具体的信号量进行控制操作。

cmd:控制选项。

IPC_STAT:将信号量的属性信息从内核读到第四个参数所以指定的struct semid_ds缓存中。

IPC_SET:修改属性信息,此时也会用到struct semid_ds结构体变量具体的修改方法同消息队列和共享内存。

IPC_RMID:删除信号量集合时,并不需要把所有的信号量都删除掉后才能删除,只需要指定semid和IPC_RMID就可以把整个信号量集合删除,其中第二个参数semnum没有被用到,所以semnum的值可以随便写,不过我们一般都是把它写为0。

所以删除整个信号量集合时,删除的写法可以统一的为:

semctl(semid, 0, IPC_RMID);

SETVAL:通过第四个参数,给集合中semnu编号的信号量设置一个int初始值。此时第四个参数就是那个int值

如果是二值信号量的话,设置初始值要么是0,要么是1;

如果信号量的目的是互斥的话,基本都是设置为1。当设置为1后,多个进程互斥操作时,那就是谁先运行就谁先操作。

如果是同步的话,初值是1还是0,这要就要看具体的情况了。

...:表示,如果用不到时可以省略不写。

第四个参数对应内容是变着的,为了应对这种变化就用到了一个联合体。

union semun {    int              val;        struct semid_ds *buf;        unsigned short  *array;  /* 不做要求 */    struct seminfo  *__buf;  /* 不做要求 */};

这个联合体类型并没有被定义在信号量相关的系统头文件中,我们使用这个联合体时,我们需要自己定义这个类型,至于联合体类型名可以自己定,不过一般都是直接沿用semun这个名字。

成员介绍:

val:存放用于初始化信号量的值

buf:存放struct semid_ds结构体变量的地址

这个联合怎么用?

当需要指定struct semid_ds缓存时

union semun sem_un; //定义一个联合体变量struct semid_ds buff; //定义一个struct semid_ds缓存sem_un.buf = &buff;  //现在整个联合体的值就是buf中缩放的buff的地址    semctl(semid, 0, IPC_STAT, sem_un); //这里将联合体传递给semctl函数,其实就是将buff的地址传递给了semctl函数

当需要指定信号量的int初始值时

union semun sem_un; sem_un.val = 1;  //现在整个联合体的值就是1    semctl(semid, 0, IPC_STAT, sem_un);

返回值

调用成功返回非-1值,失败则返回-1,errno被设置。

semop

原型

#include 
#include
#include
int semop(int semid, struct sembuf *sops, unsigned nsops); 

功能

对指定的信号量进行p操作、或者是v操作。

p操作:将信号量的值-1,当信号量的值为0时,p操作默认是阻塞的。

v操作:将信号量的值+1,v操作不存在阻塞的问题。

参数

semid:信号量集合的标识符。

sops:这个参数更好理解的写法是struct sembuf sops[]。

struct sembuf{    unsigned short sem_num;      short          sem_op;    short          sem_flg;  }

这个结构体不需要我们自己定义,因为在semop函数对应的头文件中已经定义了。

sem_num:信号量编号,决定对集合中哪一个信号量进行pv操作

sem_op:设置为-1,表示想-1进行p操作,设置1表示想+1进行v操作

sem_flg:

IPC_NOWAIT:一般情况下,当信号量的值为0时进行p操作的话,semop的p操作会阻塞。如果你不想阻塞的话,可以指定这个选项,NOWAIT就是不阻塞的意思。不过除非某些特殊情况,否则我们不需要设置为非阻塞。

SEM_UNDO:防止死锁。以二值信号量为例,当进程在v操作之前就结束时,信号量的值就会一直保持为0,那么其它进程将永远无法p操作成功,会使得进程永远休眠下去,这造成就是死锁。但是设置了SEM_UNDO选项后,如果进程在结束时没有V操作的话,OS会自动帮忙V操作,防止死锁。

nsops:用于指定数组struct sembuf sops[]元素个数。

返回值

调用成功返回0,失败则返回-1,errno被设置。

 

使用信号量实现互斥 

在不使用信号量的时候

1 #include 
2 #include
3 #include
4 #include
5 #include
6 7 void print_err(char *estr) 8 { 9 perror(estr); 10 exit(-1);11 }12 13 int main(void)14 {15 pid_t ret=0;16 int fd=-1;17 18 fd=open("./file",O_RDWR|O_CREAT|O_TRUNC,0664);19 if(-1 == fd) print_err("open file fail");20 21 ret=fork();22 if(ret>0)23 {24 while(1)25 {26 write(fd,"hello ",6);27 write(fd,"world\n",6);28 }29 }30 else if(ret == 0)31 {32 while(1)33 {34 write(fd,"hhhhh ",6);35 write(fd,"wwwww\n",6);36 }37 }38 }
View Code

输出文件file里面的内容会比较乱,这种乱不是因为写文件时笔尖乱指导致数据覆盖,而是因为父子进程交叉执行,导致父子进程的数据都被隔断。参考文章:

file内容截取

hello worldhhhhh hello wwwwwworldhhhhh hello wwwwwworldhhhhh hello wwwwwworldhhhhh hello wwwwwworldhhhhh hello wwwwwworldhhhhh hello wwwwwworldhhhhh hello wwwwwworldhhhhh hello wwwwwworldhhhhh hello wwwww
View Code

——————————————————————————————————————————————————————————————————

引入信号量机制实现互质写文件

main.c

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include "semaphore.h" 9 10 11 12 #define NSEMS 113 14 int semid;15 16 17 void signal_fun(int signo)18 {19 del_sem(semid, NSEMS);20 exit(-1);21 }22 23 int main(void)24 {25 int i = 0;26 int ret = 0;27 int fd = -1;28 int semnum_buf[1] = { 0};29 30 fd = open("./file", O_RDWR|O_CREAT|O_TRUNC, 0664);31 if(fd == -1) print_err("open file fail");32 33 semid = creat_or_get_sem(NSEMS);34 35 for(i=0; i
0)42 {43 signal(SIGINT, signal_fun);44 while(1)45 {46 semnum_buf[0] = 0;//设置要操作的信号量的编号47 p_sem(semid, semnum_buf, 1); //P操作48 write(fd, "hello ", 6);49 write(fd, "world\n", 6);50 semnum_buf[0] = 0; //设置要操作的信号量的编号51 v_sem(semid, semnum_buf, 1);//v操作52 } 53 }54 else if(ret == 0)55 {56 while(1)57 {58 semnum_buf[0] = 0;//设置要操作的信号量的编号59 p_sem(semid, semnum_buf, 1); //P操作60 write(fd, "hhhhh ", 6);61 write(fd, "wwwww\n", 6);62 semnum_buf[0] = 0; //设置要操作的信号量的编号63 v_sem(semid, semnum_buf, 1);//v操作64 } 65 }66 67 return 0;68 }
View Code

sem.c

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 11 union semun 12 { 13 int val; 14 struct semid_ds *buf; 15 unsigned short *array; /* 不做要求 */ 16 struct seminfo *__buf; /* 不做要求 */ 17 }; 18 19 #define SEM_FILE "./semfile" 20 21 void print_err(char *estr) 22 { 23 perror(estr); 24 //exit(-1); 25 } 26 27 int creat_or_get_sem(int nsems) 28 { 29 int semid; 30 int fd = -1; 31 key_t key = -1; 32 33 fd = open(SEM_FILE, O_RDWR|O_CREAT, 0664); 34 if(fd == -1) print_err("open ./semfile fail"); 35 36 key = ftok(SEM_FILE, 'a'); 37 if(key == -1) print_err("ftok fail"); 38 39 semid = semget(key, nsems, 0664|IPC_CREAT); 40 if(semid == -1) print_err("semget fail"); 41 42 return semid; 43 } 44 45 void init_sem(int semid, int semnum, int val) 46 { 47 int ret = -1; 48 union semun sem_un; 49 50 /* semnum:信号量编号 51 * SETVAL:设置信号量初始值cmd 52 * sem_un:初始值 53 */ 54 sem_un.val = val; 55 ret = semctl(semid, semnum, SETVAL, sem_un); 56 if(ret == -1) print_err("semctl fail"); 57 } 58 59 60 void del_sem(int semid, int nsems) 61 { 62 int ret = 0; 63 int i = 0; 64 65 for(i=0; i
View Code

sem.h

1 #ifndef H_SEM_H 2 #define H_SEM_H 3  4 extern void print_err(char *estr); 5 extern int creat_or_get_sem(int nsems); 6 extern void init_sem(int semid, int semnum, int val); 7 extern void del_sem(int semid, int nsems); 8 extern void p_sem(int semid, int semnum_buf[], int nsops); 9 extern void v_sem(int semid, int semnum_buf[], int nsops);10 11 #endif
View Code

输出文件file

hello worldhhhhh wwwwwhello worldhhhhh wwwwwhello worldhhhhh wwwwwhello worldhhhhh wwwwwhello worldhhhhh wwwww
View Code

 ——————————————————————————————————————————————————————————————————

通过同步让三个亲缘进程按照顺序打印出111111、222222、333333

mian.c

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include "semaphore.h" 9 10 11 12 #define NSEMS 313 14 int semid;15 16 17 void signal_fun(int signo)18 {19 del_sem(semid, NSEMS);20 exit(-1);21 }22 23 int main(void)24 {25 int i = 0;26 int ret = 0;27 int fd = -1;28 int semnum_buf[1] = { 0};29 30 //创建信号量集合31 semid = creat_or_get_sem(NSEMS);32 33 //初始化信号量集合中的每个信号量34 for(i=0; i
0)42 {43 ret = fork();44 if(ret > 0) //父进程45 {46 while(1)47 { 48 semnum_buf[0] = 2;49 p_sem(semid, semnum_buf, 1);50 printf("333333\n");51 sleep(1);52 semnum_buf[0] = 0;53 v_sem(semid, semnum_buf, 1);54 55 } 56 }57 else if(ret == 0) //子进程258 {59 while(1)60 {61 semnum_buf[0] = 1;62 p_sem(semid, semnum_buf, 1);63 printf("222222\n");64 sleep(1);65 semnum_buf[0] = 2;66 v_sem(semid, semnum_buf, 1);67 } 68 }69 }70 else if(ret == 0)//子进程171 {72 signal(SIGINT, signal_fun);73 while(1)74 {75 semnum_buf[0] = 0;76 p_sem(semid, semnum_buf, 1);77 printf("111111\n");78 sleep(1);79 semnum_buf[0] = 1;80 v_sem(semid, semnum_buf, 1);81 } 82 }83 84 return 0;85 }
View Code

sem.c

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 11 union semun 12 { 13 int val; 14 struct semid_ds *buf; 15 unsigned short *array; /* 不做要求 */ 16 struct seminfo *__buf; /* 不做要求 */ 17 }; 18 19 #define SEM_FILE "./semfile" 20 21 void print_err(char *estr) 22 { 23 perror(estr); 24 //exit(-1); 25 } 26 27 int creat_or_get_sem(int nsems) 28 { 29 int semid; 30 int fd = -1; 31 key_t key = -1; 32 33 fd = open(SEM_FILE, O_RDWR|O_CREAT, 0664); 34 if(fd == -1) print_err("open ./semfile fail"); 35 36 key = ftok(SEM_FILE, 'a'); 37 if(key == -1) print_err("ftok fail"); 38 39 semid = semget(key, nsems, 0664|IPC_CREAT); 40 if(semid == -1) print_err("semget fail"); 41 42 return semid; 43 } 44 45 void init_sem(int semid, int semnum, int val) 46 { 47 int ret = -1; 48 union semun sem_un; 49 50 /* semnum:信号量编号 51 * SETVAL:设置信号量初始值cmd 52 * sem_un:初始值 53 */ 54 sem_un.val = val; 55 ret = semctl(semid, semnum, SETVAL, sem_un); 56 if(ret == -1) print_err("semctl fail"); 57 } 58 59 60 void del_sem(int semid, int nsems) 61 { 62 int ret = 0; 63 64 //第二个参数没用上。 65 ret = semctl(semid, 0, IPC_RMID); 66 if(ret == -1) print_err("semctl del sem fail"); 67 68 remove(SEM_FILE); 69 } 70 71 void p_sem(int semid, int semnum_buf[], int nsops) 72 { 73 int i = 0; 74 int ret = -1; 75 struct sembuf sops[nsops]; 76 77 for(i=0; i
View Code

sem.h

1 #ifndef H_SEM_H 2 #define H_SEM_H 3  4 extern void print_err(char *estr); 5 extern int creat_or_get_sem(int nsems); 6 extern void init_sem(int semid, int semnum, int val); 7 extern void del_sem(int semid, int nsems); 8 extern void p_sem(int semid, int semnum_buf[], int nsops); 9 extern void v_sem(int semid, int semnum_buf[], int nsops);10 11 #endif
View Code

——————————————————————————————————————————————————————————————————

使用信号量来解决共享内存的同步问题

shm1.c

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include "semaphore.h" 15 16 17 18 #define SHM_FILE "./shmfile" 19 20 #define SHM_SIZE 4096 21 22 int shmid = -1; 23 int semid = -1; 24 void *shmaddr = NULL; 25 26 27 28 static void print_err(char *estr) 29 { 30 perror(estr); 31 exit(-1); 32 } 33 34 void create_or_get_shm(void) 35 { 36 int fd = 0; 37 key_t key = -1; 38 39 fd = open(SHM_FILE, O_RDWR|O_CREAT, 0664); 40 if(fd == -1) print_err("open fail"); 41 42 key = ftok(SHM_FILE, 'b'); 43 if(key == -1) print_err("ftok fail"); 44 45 shmid = shmget(key, SHM_SIZE, 0664|IPC_CREAT); 46 if(shmid == -1) print_err("shmget fail"); 47 48 //write(fd, &shmid, sizeof(shmid)); 49 } 50 51 char buf[300] = { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ 52 222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222\ 53 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2222222222"}; 54 55 void signal_fun(int signo) 56 { 57 shmdt(shmaddr); 58 shmctl(shmid, IPC_RMID, NULL); 59 60 del_sem(semid);//删除信号量集合 61 62 remove("./fifo"); 63 remove(SHM_FILE); 64 65 exit(-1); 66 } 67 68 69 70 int main(void) 71 { 72 int peer_pid = -1; 73 74 /* 给SIGINT信号注册捕获函数,用于删除共享内存、管道、文件等 */ 75 signal(SIGINT, signal_fun); 76 77 78 /* 创建、或者获取共享内存 */ 79 create_or_get_shm(); 80 81 //创建信号量集合 82 semid = creat_or_get_sem(2); 83 84 /* 初始化信号量集合 */ 85 int i = 0; 86 for(i=0; i<2; i++) 87 { 88 //将编号0的信号量初始化为1,其它初始化为0 89 if(i == 0) init_sem(semid, i, 1); 90 else init_sem(semid, i, 0); 91 } 92 93 //建立映射 94 shmaddr = shmat(shmid, NULL, 0); 95 if(shmaddr == (void *)-1) print_err("shmat fail"); 96 97 int semnum_buf[1] = { 0};//存放信号量的编号 98 while(1) 99 { 100 //p sem 0101 semnum_buf[0] = 0;102 p_sem(semid, semnum_buf, 1);103 104 /* 向共享内存写数据 */105 memcpy(shmaddr, buf, sizeof(buf));106 sleep(1);107 108 //v sem 1109 semnum_buf[0] = 1;110 v_sem(semid, semnum_buf, 1);111 }112 113 return 0;114 }
View Code

shm2.c

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include "semaphore.h"15 16 #define SHM_FILE "./shmfile"17 18 #define SHM_SIZE 409619 20 int shmid = -1;21 int semid = -1;22 void *shmaddr = NULL; 23 24 25 26 void print_err(char *estr)27 {28 perror(estr); 29 exit(-1);30 }31 32 void create_or_get_shm(void)33 {34 int fd = 0;35 key_t key = -1; 36 37 fd = open(SHM_FILE, O_RDWR|O_CREAT, 0664);38 if(fd == -1) print_err("open fail");39 40 key = ftok(SHM_FILE, 'b');41 if(key == -1) print_err("ftok fail");42 43 shmid = shmget(key, SHM_SIZE, 0664|IPC_CREAT);44 if(shmid == -1) print_err("shmget fail");45 46 //read(fd, &shmid, sizeof(shmid));47 }48 49 void signal_fun(int signo)50 {51 if(SIGINT == signo)52 {53 shmdt(shmaddr);54 shmctl(shmid, IPC_RMID, NULL);55 remove("./fifo");56 remove(SHM_FILE);57 58 exit(-1);59 }60 else if(SIGUSR1 == signo)61 {62 63 }64 }65 66 int main(void)67 {68 signal(SIGINT, signal_fun);69 70 /* 创建、或者获取共享内存 */71 create_or_get_shm();72 73 //获取别人创建号的信号量74 semid = creat_or_get_sem(2);75 76 //建立映射77 shmaddr = shmat(shmid, NULL, 0);78 if(shmaddr == (void *)-1) print_err("shmat fail"); 79 80 int semnum_buf[1] = { 0};//存放信号量编号 81 while(1)82 {83 //p sem 184 semnum_buf[0] = 1;85 p_sem(semid, semnum_buf, 1);86 87 //从共享内存去除数据并打印显示88 printf("%s\n", (char *)shmaddr);89 bzero(shmaddr, SHM_SIZE);//清空共享内存90 91 //v sem 092 semnum_buf[0] = 0;93 v_sem(semid, semnum_buf, 1);94 }95 96 return 0;97 }
View Code

sem.c

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 11 union semun 12 { 13 int val; 14 struct semid_ds *buf; 15 unsigned short *array; /* 不做要求 */ 16 struct seminfo *__buf; /* 不做要求 */ 17 }; 18 19 #define SEM_FILE "./semfile" 20 21 static void print_err(char *estr) 22 { 23 perror(estr); 24 //exit(-1); 25 } 26 27 int creat_or_get_sem(int nsems) 28 { 29 int semid; 30 int fd = -1; 31 key_t key = -1; 32 33 fd = open(SEM_FILE, O_RDWR|O_CREAT, 0664); 34 if(fd == -1) print_err("open ./semfile fail"); 35 36 key = ftok(SEM_FILE, 'a'); 37 if(key == -1) print_err("ftok fail"); 38 39 semid = semget(key, nsems, 0664|IPC_CREAT); 40 if(semid == -1) print_err("semget fail"); 41 42 return semid; 43 } 44 45 void init_sem(int semid, int semnum, int val) 46 { 47 int ret = -1; 48 union semun sem_un; 49 50 /* semnum:信号量编号 51 * SETVAL:设置信号量初始值cmd 52 * sem_un:初始值 53 */ 54 sem_un.val = val; 55 ret = semctl(semid, semnum, SETVAL, sem_un); 56 if(ret == -1) print_err("semctl fail"); 57 } 58 59 60 void del_sem(int semid) 61 { 62 int ret = 0; 63 64 ret = semctl(semid, 0, IPC_RMID); 65 if(ret == -1) print_err("semctl del sem fail"); 66 67 remove(SEM_FILE); 68 } 69 70 void p_sem(int semid, int semnum_buf[], int nsops) 71 { 72 int i = 0; 73 int ret = -1; 74 struct sembuf sops[nsops]; 75 76 for(i=0; i
View Code

sem.h

1 #ifndef H_SEM_H 2 #define H_SEM_H 3  4 extern int creat_or_get_sem(int nsems); 5 extern void init_sem(int semid, int semnum, int val); 6 extern void del_sem(int semid); 7 extern void p_sem(int semid, int semnum_buf[], int nsops); 8 extern void v_sem(int semid, int semnum_buf[], int nsops); 9 10 #endif
View Code

 

 

 

 

 

转载于:https://www.cnblogs.com/kelamoyujuzhen/p/9394837.html

你可能感兴趣的文章
EZOJ #257
查看>>
浅谈MySQL中的查询优化
查看>>
PYTHON RE正则表达式
查看>>
QT中定时器的使用方法
查看>>
Prototype 原型模式
查看>>
本地Git仓库和远程仓库的创建及关联
查看>>
牛课练习赛34 Flittle w and Discretization 主席树维护Mex
查看>>
REST Security with JWT using Java and Spring Security
查看>>
oracle迁移mysql数据库注意(转)
查看>>
SynchronousQueue、LinkedBlockingQueue、ArrayBlockingQueue性能测试(转)
查看>>
wamp的安装使用(转)
查看>>
[android] 切换界面的通用处理
查看>>
C#用正则表达式一键Unicode转UTF8(解决LitJson中文问题)
查看>>
linux shell通配符、元字符、转义符
查看>>
sql中某条件不为空,可能有的小祖宗会喷了,这还用总结?emmm,我渣,我觉得有一点意思对于第二种(土味)...
查看>>
小程序使用smart模板的方法
查看>>
HTPC家庭娱乐和XBOX未来发展畅想<另:创业工作机会>
查看>>
MUI下拉刷新
查看>>
leetcode------Search a 2D Matrix
查看>>
数字水印技术的研究现状与发展趋势
查看>>