当前位置:网站首页>Process communication - semaphore
Process communication - semaphore
2022-07-03 09:37:00 【zhyg_ three hundred and twenty-one】
1.sem
- struct sem {
- short sempid; /* pid of last operation */
- ushort semval; /* current value */
- ushort semncnt; /* num procs awaiting increase in semval */
- ushort semzcnt; /* num procs awaiting semval = 0 */
- };
sem_pid The member saves the process of the last semaphore operation pid.
sem_semval Members store the count value of semaphores .
sem_semncnt The member holds the number of processes waiting to use resources .
sem_semzcnt Members save the number of processes waiting for resources to be completely idle .
2.semun
semun The consortium is in senctl() Use in a function , Provide senctl() Information required for operation .
- union semun {
- int val; /* value for SETVAL */
- struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
- ushort *array; /* array for GETALL & SETALL */
- struct seminfo *__buf; /* buffer for IPC_INFO */
- void *__pad;
- };
3.sembuf
sembuf The structure is semop() Function is used to define basic operations on semaphore objects
- struct sembuf {
- unsigned short sem_num; /* semaphore index in array */
- short sem_op; /* semaphore operation */
- short sem_flg; /* operation flags */
- };
sem_num The member is the sequence number of the semaphore receiving the operation in the semaphore array ( The array subscript ).
sem_op Member defines the operation to be performed ( It can be positive 、 Negative and zero ).
sem_flg It is a sign of controlling operation behavior .
4.semid_qs
and msgqid_ds similar ,semid_qs Structure is used by the system to store information about each semaphore object .
- struct semid_ds {
- struct ipc_perm sem_perm; /* permissions .. see ipc.h */
- __kernel_time_t sem_otime; /* last semop time */
- __kernel_time_t sem_ctime; /* last change time */
- struct sem *sem_base; /* ptr to first semaphore in array */
- struct sem_queue *sem_pending; /* pending operations to be processed */
- struct sem_queue **sem_pending_last; /* last pending operation */
- struct sem_undo *undo; /* undo requests on this array */
- unsigned short sem_nsems; /* no. of semaphores in array */
- };
among ,
sem_perm Members store the access rights of semaphore objects and other information .
sem_otime Members saved the last semop() Time of operation .
sem_ctime The member saves the time when the semaphore object was last changed .
sem_base The pointer stores the starting address of the semaphore array .
sem_pending The pointer saves the operation that has not been carried out .
sem_pending_last The pointer holds the last operation that has not been performed .
sem_undo Members saved undo The number of requests .
sem_nsems Member holds the number of members of the semaphore array .
Related functions
1.semget()
Use semget() Function to create a new semaphore object or get the identifier of an existing object .
system call : semget()
Function declaration : int semget(key_t key,int nsems,int semflg);
Return value : semaphore set IPC identifier on success
- int open_semaphore_set(key_t keyval, int numsems)
- {
- int sid;
- if(!numsems) return(-1);
- if((sid=semget(keyval,numsems,IPC_CREAT|0660))==-1)
- {
- return(-1);
- }
- return(sid);
- }
2.semop()
Use this function to change the state of each semaphore in the semaphore object .
system call : semop()
Function declaration : int semop(int semid, struct sembuf *sops, unsigned int nsops);
Return value : 0 on success (all operations performed)
The first parameter semid Is the identifier of the semaphore object to be operated .
The second parameter sops yes sembuf Array of , It defines the semop() The sequence of operations to be performed by the function .
The third parameter nsops preserved sops Length of array , That is to say semop() The number of operations that the function will perform .
3.semctl()
And message queues msgctl() Function similar to ,semctl() Function is used to directly control the semaphore object
system call : semctl()
Function declaration : int semctl(int semid, int semnum, int cmd, union semun arg);
Return value : positive integer on success
Comparing the parameters of these two functions, we find some subtle differences . First , Because the semaphore object is actually a collection of multiple semaphores rather than a single individual , So when operating , It is not only necessary to specify the identifier of the object , You also need to use the sequence number of semaphores in the set to specify specific semaphore individuals .
Both functions have cmd Parameters , Specifies the specific operation of the function . however , and msgctl() Compared to the function , semctl() Functions can do much more :
IPC_STAT Get semaphore object semid_ds structural information , And store it in arg Parameters in buf The pointer returns .
IPC_SET use arg Parameters in buf To set the... Of the semaphore object semid_ds structural information . Just like the message queue object , Only a few parameters can be set by this function .
IPC_RMID Delete semaphore object from memory .
GETALL Get the values of all semaphores in the semaphore object , And store it arg In the parameter array Array returns .
GETNCNT Returns the number of processes waiting to use a semaphore controlled resource .
GETPID Returns the last call to a semaphore semop() The process of the function pid.
GETVAL Return the value of a semaphore of the object .
GETZCNT Returns the number of processes waiting for the resources controlled by a semaphore to be fully used .
SETALL use arg Parameters in array Array value to set the value of each semaphore in the object .
SETVAL use arg Parameters in val Member to set the value of a semaphore in the object .
- int get_sem_val(int sid, int semnum)
- {
- return(semctl(sid,semnum,GETVAL,0));
- }
- void init_semaphore(int sid, int semnum, int initval)
- {
- union semun semopts;
- semopts.val=initval;
- semctl(sid, semnum, SETVAL, semopts);
- }
In message queues and semaphore objects , There are IPC_STAT and IPC_SET The operation of . However, due to the different types of passed parameters , Caused the difference in their use . stay msgctl() Function ,IPC_STAT The operation is simply to put the kernel msgqid_ds junction
The address of the structure is given buf Parameters ( It's a pointer ). And in the semctl() Function , IPC_STAT The operation is to semid_ds Copy the contents of to arg Parametric buf In the memory indicated by the member pointer . therefore , The following code will generate errors , and msgctl() Functional
Similar code does not :
- void getmode(int sid)
- {
- int rc;
- union semun semopts;
- /* The following statement will produce errors */
- if((rc=semctl(sid, 0, IPC_STAT, semopts))==-1)
- {
- perror("semctl");
- }
- printf("Pemission Mode were %o/n", semopts.buf->sem_perm.mode);
- return;
- }
- void getmode(int sid)
- {
- int rc;
- union semun semopts;
- struct semid_ds mysemds;
- /* to buf The pointer prepares a piece of memory */
- semopts.buf=&mysemds;
- /* Now? OK 了 */
- if((rc=semctl(sid, 0, IPC_STAT, semopts))==-1)
- {
- perror("semctl");
- }
- printf("Pemission Mode were %o/n", semopts.buf->sem_perm.mode);
- return;
- }
example :
- semtool.c
- #include <stdio.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #define SEM_RESOURCE_MAX 1 /*Initial value of all semaphores*/
- void opensem(int *sid, key_t key);
- void createsem(int *sid, key_t key, int members);
- void locksem(int sid, int member);
- void unlocksem(int sid, int member);
- void removesem(int sid);
- unsigned short get_member_count(int sid);
- int getval(int sid, int member);
- void dispval(int sid,int member);
- void changemode(int sid, char *mode);
- void usage(void);
- int main(int argc, char *argv[])
- {
- key_t key;
- int semset_id;
- if(argc == 1) usage();
- /*Create unique key via call to ftok()*/
- key=ftok(".",'s');
- switch(tolower(argv[1][0]))
- {
- case 'c':
- if(argc!=3)usage();
- createsem(&semset_id, key, atoi(argv[2]));
- break;
- case 'l':
- if(argc!=3) usage();
- opensem(&semset_id, key);
- locksem(semset_id, atoi(argv[2]));
- break;
- case 'u':
- if(argc!=3) usage();
- opensem(&semset_id, key);
- unlocksem(semset_id, atoi(argv[2]));
- break;
- case 'd':
- opensem(&semset_id,key);
- removesem(semset_id);
- break;
- case 'm':
- opensem(&semset_id, key);
- changemode(semset_id, argv[2]);
- break;
- default:
- usage();
- }
- return(0);
- }
- void opensem(int *sid, key_t key)
- {
- /*Open the semaphore set ---do not creat!*/
- if((*sid=semget(key, 0 , 0666)==-1)
- {
- printf("Semaphore set does not exist!/n");
- exit(1);
- }
- }
- void createsem(int *sid, key_t key, int members)
- {
- int cntr;
- union semun semopts;
- if(members > SEMMSL){
- printf("Sorry,max number of semaphores in a set is %d/n",SEMMSL);
- exit(1);
- }
- printf("Attempting to create new semaphore set with %d members/n",members);
- if((*sid=semget(key, members, IPC_CREAT|IPC_EXCL|0666))==-1)
- {
- fprintf(stderr,"Semaphore set already exist!/n");
- exit(1);
- }
- semopts.val= SEM_RESOURCE_MAX;
- /*Initialize all members(could be done with SETALL)*/
- for(cntr=0;cntr<members;cntr++)
- {
- semctl(*sid, cntr, SETVAL, semopts);
- }
- }
- void locksem(int sid, int member)
- {
- struct sembuf sem_lock={0, -1, IPC_NOWAIT};
- if(member <0 ||member>(get_member_count(sid) -1))
- {
- fprintf(stderr,"semaphore member %d out of range/n", member);
- return;
- }
- /*Attempt to lock the semphore set*/
- if(!getval(sid, member))
- {
- fprintf(stderr,"Semaphore resources exhausted (no lock)/n")
- exit(1);
- }
- sem_lock.sem_num =member;
- if((semop(sid, &sem_lock, 1)==-1)
- {
- fprintf, "Lock faild/n");
- exit(1);
- }
- else
- printf("Semaphore resources decremented by one (locked)/n");
- dispval(sid ,member);
- }
- void unlocksem(int sid, int member)
- {
- struct sembuf sem_unlock={member, 1, IPC_NOWAIT};
- int semval;
- if(member<0 || member>(get_member_count(sid)-1))
- {
- fprintf(stderr,"Semaphore member %d out of range/n",member);
- return;
- }
- /*Is the semaphore set locked? */
- semval =getval(sid, member);
- if(semval==SEM_REOURSE_MAX){
- fprintf(stderr, "Semaphore not locked!/n");
- exit(1);
- }
- sem_unlock.sem_num = member;
- /*Attempt to lock the semaphore set*/
- if((semop(sid, &sem_unlock, 1))==-1)
- {
- fprintf(stderr, "Unlock failed/n");
- exit
- }
- else
- printf("Semaphore resources incremented by one(unlocked)/n");
- dispval(sid, member);
- }
- void removesem(int sid)
- {
- semctl(sid, 0, IPC_RMID,0);
- print("Semaphore removed/n");
- }
- unsigned short get_member_count(int sid)
- {
- union semum semopts;
- struct semid_ds mysemds;
- semopts.buf= &mysemds;
- /*Return number of member in the semaphore set*/
- int rc;
- if((rc=semctl(sid, 0, IPC_STAT, semopts))==-1)
- {
- perror("semctl");
- return(-1)
- }
- return(semopts.buf->sem_nsems);
- }
- int getval(int sid, int member)
- {
- int semval;
- semval= semctl(sid, member,GETVAL, 0)
- reval semval;
- }
- void changemode(int sid, char *mode)
- {
- int rc;
- union semun semopts;
- struct semid_ds mysemds;
- /*Get current values for internal data structure */
- semopts.buf=&mysemds;
- rc = semctl(sid, 0, IPC_STAT, semopts);
- if(rc ==-1)
- {
- perror("semctl");
- exit(1);
- }
- printf("Old permission were %o/n", semopts.buf->perm.mode);
- /* Change the permission on the semaphore */
- sscanf(mode,"%ho",&semopts.buf->sem_perm.mode);
- /*Update the internal data structure */
- semctl(sid,0, IPC_SET, semopts);
- printf("Updated....../n");
- }
- void dispval(int sid, int member)
- {
- int semval;
- semval= semctl(sid, member, GETVAL,0);
- printf("semval for member %d is %d/n", member ,semval);
- }
- void usage(void)
- {
- fprintf(stderr, "semtool -Autility for thinking with semaphores/n");
- fprintf(stderr, "/nUSAGE: semtool (c)reate <semcount>/n");
- fprintf(stderr, " (l)ock <sem #>/n");
- fprintf(stderr, " (u)nlock <sem #>/n");
- fprintf(stderr, " (d)elete/n");
- fprintf(stderr, " (m)ode <mode>/n");
- exit(1);
- }
边栏推荐
- Win10 install elk
- Global KYC service provider advance AI in vivo detection products have passed ISO international safety certification, and the product capability has reached a new level
- Leetcode daily question (2305. fair distribution of cookies)
- 307. Range Sum Query - Mutable
- Leetcode daily question (2109. adding spaces to a string)
- LeetCode每日一题(1362. Closest Divisors)
- Hudi integrated spark data analysis example (including code flow and test results)
- Trial of the combination of RDS and crawler
- Powerdesign reverse wizard such as SQL and generates name and comment
- LeetCode每日一题(516. Longest Palindromic Subsequence)
猜你喜欢

Win10安装ELK

Spark 集群安装与部署

Arduino handles JSON data, arduinojson assistant

The rise and fall of mobile phones in my perspective these 10 years

一款开源的Markdown转富文本编辑器的实现原理剖析

What do software test engineers do? Pass the technology to test whether there are loopholes in the software program

PolyWorks script development learning notes (III) -treeview advanced operation

Detailed steps of windows installation redis

Flink learning notes (IX) status programming

【Kotlin疑惑】在Kotlin类中重载一个算术运算符,并把该运算符声明为扩展函数会发生什么?
随机推荐
Crawler career from scratch (I): crawl the photos of my little sister ① (the website has been disabled)
文件系统中的目录与切换操作
The rise and fall of mobile phones in my perspective these 10 years
Navicat, MySQL export Er graph, er graph
小王叔叔的博客目录【持续更新中】
IDEA 中使用 Hudi
Powerdesign reverse wizard such as SQL and generates name and comment
LeetCode每日一题(2090. K Radius Subarray Averages)
Idea uses the MVN command to package and report an error, which is not available
LeetCode每日一题(968. Binary Tree Cameras)
Starting from 0, use pnpm to build a demo managed by monorepo
PolyWorks script development learning notes (I) - script development environment
LeetCode每日一题(745. Prefix and Suffix Search)
LeetCode每日一题(1362. Closest Divisors)
Filter comments to filter out uncommented and default values
LeetCode每日一题(2212. Maximum Points in an Archery Competition)
Using Hudi in idea
Numerical analysis notes (I): equation root
Flink-CDC实践(含实操步骤与截图)
Hudi learning notes (III) analysis of core concepts