进程间通信之信号量semaphore--linux内核剖析( 七 )
int semop(int semid, struct sembuf *opsptr, size_t nops);
参数描述semid是semget返回的semid信号量标示符opsptr指向信号量操作结构数组nopsopsptr所指向的数组中的sembuf结构体的个数该函数执行成功返回0 , 失败返回-1;
第二个参数sops为一个结构体数组指针 , 结构体定义在sys/sem.h中 , 结构体如下
struct sembuf {unsigned short sem_num; /* semaphore index in array */short sem_op; /* semaphore operation */short sem_flg; /* operation flags */};
sem_num 操作信号的下标 , 其值可以为0 到nops sem_flg为该信号操作的标志:其值可以为0、IPC_NOWAIT 、 SEM_UNDOsem_flg标识描述0在对信号量的操作不能执行的情况下 , 该操作阻塞到可以执行为止;IPC_NOWAIT在对信号量的操作不能执行的情况下 , 该操作立即返回;SEM_UNDO当操作的进程推出后 , 该进程对sem进行的操作将被取消;
sem_op取值描述>0>0则信号量加上它的值 , 等价于进程释放信号量控制的资源=0=0若没有设置IPC_NOWAIT ,那么调用进程将进入睡眠状态 , 直到信号量的值为0 , 否则进程直接返回则信号量加上它的值 , 等价于进程申请信号量控制的资源 , 若进程设置IPC_NOWAIT则进程再没有可用资源情况下 , 进程阻塞 , 否则直接返回 。
例如 , 当前semval为2 , 而sem_op = -3 , 那么怎么办?
注意:semval是指semid_ds中的信号量集中的某个信号量的值
#include #include #include #include #include int main(int argc,char *argv[]){intc,i,flag,semid,nops;structsembuf *ptr;flag = 0;//根据命令行参数设置操作模式while( ( c = getopt(argc,argv,"nu")) != -1){switch(c){case 'n':flag |= IPC_NOWAIT;//非阻塞break;case 'u':flag |= SEM_UNDO;//不可恢复break;}}if(argc - optind < 2){printf("usage: semops [-n] [-u]operation...");exit(0);}//打开一个已经存在的信号量集合if((semid = semget(ftok(argv[optind],0),0,0)) == -1){perror("semget() error");exit(-1);}optind++;//指向当前第一个信号量的位置nops = argc - optind;//信号量个数ptr = calloc(nops,sizeof(struct sembuf));for(i=0;i对信号集实行控制操作(semval的赋值等)int semctl(int semid, int semum, int cmd, ../* union semun arg */);
参数描述semid是信号量集合;semnum是信号在集合中的序号;semum是一个必须由用户自定义的结构体 , 在这里我们务必弄清楚该结构体的组成:
union semun{int val; // cmd == SETVALstruct semid_ds *buf // cmd == IPC_SET或者 cmd == IPC_STATushort *array; // cmd == SETALL , 或 cmd = GETALL};
值描述IPC_STAT读取一个信号量集的数据结构semid_ds , 并将其存储在semun中的buf参数中 。 IPC_SET设置信号量集的数据结构semid_ds中的元素ipc_perm , 其值取自semun中的buf参数 。 IPC_RMID将信号量集从系统中删除GETALL用于读取信号量集中的所有信号量的值 , 存于semnu的array中SETALL设置所指定的信号量集的每个成员semval的值GETPID返回最后一个执行semop操作的进程的PID 。 LSETVAL把的val数据成员设置为当前资源数GETVAL把semval中的当前值作为函数的返回 , 即现有的资源数 , 返回值为非负数 。
val只有cmd ==SETVAL时才有用 , 此时指定的semval = arg.val 。
注意:当cmd == GETVAL时 , semctl函数返回的值就是我们想要的semval 。 千万不要以为指定的semval被返回到arg.val中 。
array指向一个数组 ,
当cmd==SETALL时 , 就根据arg.array来将信号量集的所有值都赋值;
当cmd ==GETALL时 , 就将信号量集的所有值返回到arg.array指定的数组中 。
buf 指针只在cmd==IPC_STAT 或IPC_SET 时有用 , 作用是semid 所指向的信号量集
(semid_ds机构体) 。 一般情况下不常用 , 这里不做谈论 。
另外 , cmd == IPC_RMID还是比较有用的 。
- 通气会|12月4~6日,2020中国信息通信大会将在成都举行
- 中国|浅谈5G移动通信技术的前世和今生
- 星期一|亚马逊:黑五与网络星期一期间 第三方卖家销售额达到48亿美元
- 建设|龙元建设中标中国移动宁波信息通信产业园二期施工项目
- IPO|三旺通信IPO:产品结构相对单一业务规模较小 研发人员占员工总数33%
- 空间|垃圾文件正在吞噬你的C盘空间用这四种方法,还你一个干净的C盘
- 广告点击|广告效果评估:30天的广告时间评估最全面
- 要来|折叠屏iPhone终于要来了!可惜发布的时间有点晚,你愿意等吗?
- 智能手机品|越南手机悄然崛起!创立短短2年时间,在当地接连击退苹果、小米
- 科技|短视频行业领先 云想科技成长空间广阔