the fourth argument:
union semun { int val; /* Value for SETVAL */ struct semid_ds* buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short* array; /* Array for GETALL, SETALL */ struct seminfo* __buf; /* Buffer for IPC_INFO(Linux-specific) */ }; //<sys/sem.h> struct semid_ds { struct ipc_perm sem_perm; /* Ownership and permissions */ time_t sem_otime; /* Last semop time */ time_t sem_ctime; /* Last change time */ unsigned short sem_nsems; /* No. of semaphores in set */ }; //<sys/ipc.h> struct ipc_perm { key_t __key; /* Key supplied to semget(2) */ uid_t uid; /* Effective UID of owner */ gid_t gid; /* Effective GID of owner */ uid_t cuid; /* Effective UID of creator */ gid_t cgid; /* Effective GID of creator */ unsigned short mode; /* Permissions */ unsigned short __seq; /* Sequence number */ }; int res=semctl(semid,0,SETVAL,5); if(-1==res) perror("semctl"),exit(-1); int res=semctl(semid,0,IPC_RMID); if(-1==res) perror("semctl"),exit(-1); semop(): //操作指定的信号量集,成功返回0,失败返回-1设errno int semop(int semid, struct sembuf *sops, unsigned nsops);semid:信号集的ID(returned by semget())
sops:结构体指针, 既可以指向结构体变量, 也可以指向结构体数组信号量集本质上是若干个信号量的集合, 可以实现对信号量的批处理
nsops:结构体指针指向的元素个数, 也就是数组的大小
例子 Sys V IPC sem #include<unistd.h> #include<sys/types.h> #include<sys/ipc.h> #include<sys/sem.h> #include<signal.h> #include<stdio.h> #include<stdlib.h> int main(){ //get key key_t key=ftok(".",200); if(-1==key) perror("ftok"),exit(-1); printf("key=%d\n",key); //create sem int semid=semget(key,0,0); if(-1==semid) perror("semget"),exit(-1); printf("semid=%d\n",semid); //creat 10 children to take the shared resource int i=0; for(i=0;i<10;i++){ //创建10个进程, 当然,需要只给parent或child单独fork(), 否则就是2^10个进程 pid_t pid=fork(); if(-1==pid) perror("fork"),exit(-1); if(0==pid){ struct sembuf buf; //准备占用资源, sem_op-1 buf.sem_num=0; //信号量集下标 buf.sem_op=-1; //信号量-1 buf.sem_flg=0; //操作标志 int res=semop(semid,&buf,1/*结构体变量的个数*/); if(-1==res) perror("semop"),exit(-1); sleep(20); //模拟正在占用共享资源 buf.sem_op=1; //占用完了, sem_op+1 res=semop(semid,&buf,1); if(-1==res) perror("semop"),exit(-1); exit(0); //终止子进程, 自然也就跳出了循环,防止再fork() // break; } } return 0; } //出现抢占的效果, 还没有全部释放完毕的时候就有进程抢到了已经释放的进程