信号量--System V信号量 与 Posix信号量

网友投稿 543 2022-05-30

信号量是什么

信号量是一种计数器,用来控制对多个进程/线程共享的资源进行访问。常和锁一同使用。

在某个进程/线程正在对某个资源进行访问时,信号量可以阻止另一个进程/线程去打扰。

生产者和消费者模型是信号量的典型使用。

为什么信号量分两套(两套有什么区别)

简要的说,Posix是“可移植操作系统接口(Portable Operating System Interface )的首字母简写,但它并不是一个单一的标准,而是一个电气与电子工程学会即IEEE开发的一系列标准,它还是由ISO(国际标准化组织)和IEC(国际电工委员会)采纳的国际标准。而System v是Unix操作系统众多版本的一个分支,它最初是由AT&T在1983年第一次发布,System v一共有四个版本,而最成功的是System V Release 4,或者称为SVR4。这样看来,一个是Unix 的标准之一(另一个标准是Open Group),一个是Unix众多版本的分支之一(其他的分支还有Linux跟BSD),应该来说,Posix标准正变得越来越流行,很多厂家开始采用这一标准。

那么两者有什么区别,或者说,应用场景:

1、POSIX信号量常用于线程;system v信号量常用于进程的同步。

2、从使用的角度,System V 信号量的使用比较复杂,而 POSIX 信号量使用起来相对简单。

3、对 POSIX 来说,信号量是个非负整数。而 System V 信号量则是一个或多个信号量的集合,它对应的是一个信号量结构体,这个结构体是为 System V IPC 服务的,信号量只不过是它的一部分。

4、Posix信号量是基于内存的,即信号量值是放在共享内存中的,它是由可能与文件系统中的路径名对应的名字来标识的。而System v信号量则是基于内核的,它放在内核里面。

5、POSIX 信号量的头文件是 ,而 System V 信号量的头文件是

6、Posix还有有名信号量,一般用于进程同步, 有名信号量是内核持续的。

怎么实现呢?

1、新建信号量

system V

#include #include #include int semget(key_t key,int nsems,int semflg); /* nsems:创建多少个 semflg:IPC_CREAT、IPC_EXCL; */

1

2

3

4

5

6

7

8

9

利用System V函数包装建立信号量的代码;

typedef int sem_t; union semun { int val; struct semid_ds *buf; //semid_ds的指针 unsigned short *array; //数组类型 } arg; //定义一个全局变量 sem_t CreateSem(key_t key,int value) { union semun sem; //信号量结构变量 sem_t sem_id; sem.val = value; //设置初始值 sem_id = semget(key,0,IPC_CREAT|0666); //获取信号量id if(sem_id == -1) { printf("create sem failed\n"); exit(-1); } semctl(sem_id,0,SETVAL,sem); //发送命令,建立value个初始信号量 return sem_id; }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

Posix信号量:直接用那个函数就好了,可以加一个报错保险。

【后面的栗子都一样,Posix就这么简单】

2、PV操作(增减信号量)

System V

/* 参数释义: struct sembuf { ushort sem_num; //信号量的编号 short sem_op; //信号量的操作 {正负零} short sem_flg; //信号量的操作标志 {NOWAIT} }; //sem_op取0表示将信号量设为睡眠状态,直到信号量的值为0为止 nsops:该数组中操作的个数 */

1

2

3

4

5

6

7

8

9

10

11

12

int Sem_P(sem_t semid) { struct sembuf sops = {0,+1,IPC_NOWAIT}; return (semop(semid,&sops,1)); }

1

2

3

4

5

intSem_V(sem_t semid) { struct sembuf sops = {0,-1,IPC_NOWAIT}; return (semop(semid,&sops,1)); }

1

2

3

4

5

P操作:进行增加一个信号量的值的操作

V操作:进行减少一个信号量的值的操作

Posix

P:sem_post(sem_t *sem);

V:sem_wait(sem_t *sem);

3、控制信号量参数

#include #include #include int semctl(int semid,int semnum,int cmd,...); /* 该函数是在信号量的集合上执行控制操作函数。 参数释义: semnum:将要被执行操作的信号量编号。对于集合中的第一个信号量,它的值为0。 cmd: IPC_STAT:获取某个集合的semid_ds结构,并把它存在semun联合体的buf中。 IPC_SET:设置某个集合的semid_ds中的ipc_perm成员的值。该命令所取值从buf中获取。 IPC_RMID:从内核删除该集合。 GETTALL:用于获取集合中所有的信号量的值,存放在semun联合体的array中。 GETPID:返回最后一次调用semop的PID。 GETVAL:返回集合中某个信号量的值。 GETZCNT:返回正在等待资源利用率达到百分百的进程的数目。 SETALL:把集合中所有信号量的值设置为semun联合体中array中的值。 SETVAL:把集合中某个信号量的值设置为semun联合体中val的值。 */

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

//栗子就不放了

4、销毁信号量

System V

void DestroySem(sem_t semid) { union semun sem; sem.val = 0; se,ctl(semid,0,IPC_RMID,sem); }

1

2

3

4

5

6

最后,放一串生产消费者的代码

//实现线程互斥 #include #include #include #include #include #include using namespace std; sem_t sem; void* productor(void* arg) { while(1) { sem_wait(&sem); cout << "create noodle!!!" << endl; sem_post(&sem); usleep(10); } return NULL; } void* consumer(void* arg) { while(1) { sem_wait(&sem); cout << "eat noodle!!!" << endl; sem_post(&sem); usleep(10); } return NULL; } int main() { pthread_t tid1,tid2; sem_init(&sem, 0, 1); pthread_create(&tid1, NULL, productor, NULL); pthread_create(&tid2, NULL, consumer, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); sem_destroy(&sem); return 0; }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

信号量--System V信号量 与 Posix信号量

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

任务调度

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:DAOS 分布式异步对象存储|代理
下一篇:Java 多线程与高并发
相关文章