抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

信号量通信

semaphore.h

信号量创建和初始化sem_init

1
int sem_init(sem_t *sem, int pshared, unsigned int value);
  • sem,初始化的信号量

  • pshared参数:

    • pshared为0,表示信号量在线程间共享,放置在所有线程可见的位置,如全局变量
    • pshared非为0,表示信号量在进程间共享,放置在所有进程可见的位置,如使用sem_openshm_openmmap等访问共享内存
      • 因为通过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
2
3
4
5
6
union semun{
int val; //cmd为SETVAL时,用于指定信号量值
struct semid_ds *buf; //cmd为IPC_STAT时或IPC_SET时生效
unsigned short *array; //cmd为GETALL或SETALL时生效
struct seminfo *_buf; //cmd为IPC_INFO时生效
};
1
int semop(int semid, struct sembuf *sops, unsigned nsops);

使用信号量,对信号量的值操作

  • semidsemget返回的信号量标识符
  • spos,操作方法数组,对信号量集的信号量操作集合
  • nsops,sops数组的长度

sembuf结构如下:

1
2
3
4
5
struct sembuf{
short sem_num; //信号量在信号量集中的编号
short sem_op; //操作方法,-1表示P操作,1表示V操作
short sem_flag; //标志位,通常SEM_UNDO让进程退出自动释放信号量
};

评论