信号量通信
semaphore.h
信号量创建和初始化sem_init
1 | int sem_init(sem_t *sem, int pshared, unsigned int value); |
sem
,初始化的信号量pshared参数:
- pshared为0,表示信号量在线程间共享,放置在所有线程可见的位置,如全局变量
- pshared非为0,表示信号量在进程间共享,放置在所有进程可见的位置,如使用
sem_open
、shm_open
、mmap
等访问共享内存- 因为通过
fork()
创建的子进程会继承父进程的虚拟地址,但是cow会让其有独立不同于父进程的物理空间,导致地址相同但值不同
- 因为通过
value
信号量初始值成功返回0,失败返回1
int sem_post(sem_t *sem);
- 信号量值加1
int sem_wait(sem_t *sem);
- 信号量值减1
int sem_destroy(sem_t *sem);
- 信号量销毁
非亲缘关系使用:sem_open
通过信号量名打开
1 | sem_t *sem_open (const char *__name, int __oflag, ...) |
__oflag
设置打开方式,fcntl.h
中定义了很多常用方式O_CREAT
,如果不存在,则创建O_RDONLY
,只读模式O_WRONLY
,只写模式O_RDWR
,读写模式O_APPEND
,末尾追加O_EXCL
,如果已存在,则返回 -1,并且修改errno的值O_TRUNC
,如果文件存在,并且以只写/读写方式打开,则清空文件全部内容O_NOCTTY
,如果路径名指向终端设备,不要把这个设备用作控制终端。O_NONBLOCK
,如果路径名指向FIFO/块文件/字符文件,则把文件的打开和后继I/O设置为非阻塞模式O_DSYNC
,等待物理 I/O 结束后再 write。在不影响读取新写入的数据的前提下,不等待文件属性更新。O_RSYNC
,read 等待所有写入同一区域的写操作完成后再进行O_SYNC
,等待物理 I/O 结束后再 write,包括更新文件属性的 I/O
sys/sem.h
另一种使用信号量的方式
1 | int semget(key_t key, int nsems, int semflg); |
成功返回信号量标识符,否则返回-1
key
,表示该信号量集的整数nsems
,创建的信号量的数目semflg
,标记位,设置权限等,如IPC_PRIVATE
表示进程私有
1 | int semctl(int semid, int semnum, int cmd, ...); |
操作和控制信号量
semid
,semget返回的信号量标识符semnum
,所操作信号在信号量集中的编号cmd
,操作方法SETVAL
设置信号量值
- 最后参数与cmd参数有关,传入如下共用体执行具体操作
1 | union semun{ |
1 | int semop(int semid, struct sembuf *sops, unsigned nsops); |
使用信号量,对信号量的值操作
semid
,semget
返回的信号量标识符spos
,操作方法数组,对信号量集的信号量操作集合nsops
,sops数组的长度
sembuf结构如下:
1 | struct sembuf{ |