Semaphore for communication between processes

1.

The semaphore itself does not have the function of data exchange. It is essentially just a data operation lock. It realizes inter-process communication by controlling critical resources, and it realizes functions such as data synchronization and mutual exclusion in the process.
Each semaphore maintains a structure as follows:

struct semid_ds {
    
    
struct ipc_perm sem_perm; /* 信号量集的操作许可权限 */
struct sem *sem_base; /* 某个信号量sem结构数组的指针,当前信号量集
中的每个信号量对应其中一个数组元素 */
ushort sem_nsems; /* sem_base 数组的个数 */
time_t sem_otime; /* 最后一次成功修改信号量数组的时间 */
time_t sem_ctime; /* 成功创建时间 */
};

struct sem {
    
    
ushort semval; /* 信号量的当前值 */
short sempid; /* 最后一次返回该信号量的进程ID 号 */
ushort semncnt; /* 等待semval大于当前值的进程个数 */
ushort semzcnt; /* 等待semval变成0的进程个数 */
};

2.

There are two operations when the semaphore is working, namely p operation, v operation, p(sv): if the value of sv is greater than zero, decrement it by 1; if its value is zero, suspend the execution of the process ( Apply for resources)v(sv): If there are other processes that are suspended due to waiting for sv, let it resume running. If no process is suspended due to waiting for sv, add 1 to it. (Release resources) Usage example
:

void p_func(int id)
{
    
    
	struct sembuf sb;
	sb.sem_num = 0;
	sb.sem_op = -1;
	sb.sem_flg = 0;
	semop(id,&sb,1);
}

void v_func(int id)
{
    
    
	struct sembuf sb;
	sb.sem_num = 0;
	sb.sem_op = 1;
	sb.sem_flg = 0;
	semop(id,&sb,1);
}

3. Related functions

    semget:int  semget(key_t  key,   int nsems,  int semflg)
  • key parameter: It can be obtained with the ftok function.
  • nsems parameter: When nsems>0: Create a semaphore set of letters, specify the number of semaphores in the set, and do not change once created. When nsems==0 : access an existing collection.
  • semflg parameters: IPC_CREATE and IPC_EXCL
  • Return value: Returns an integer of the semaphore identifier, which will be used by the semop and semctl functions, or -1 on failure.
    After successful creation, the semaphore structure is set:
    The uid and gid members of .sem_perm are set to the effective user ID and effective group ID of the calling process. The read and
    write permission bits in the .oflag parameter are stored in sem_perm.mode
    . .sem_otime is set to 0 , sem_ctime is set to the current time
    . sem_nsems is set to the value of the nsems parameter
semop:int   semop(int  semid,   struct  sembuf*  sops,   size_t  nsops)
  • semid parameter: the semaphore identifier generated by semget.
  • struct sembuf:
struct sembuf {
    
    
short sem_num; // 要操作的信号量在信号量集里的编号,
short sem_op; // 信号量操作(一般是  v:1  或   p:-1)
short sem_flg; // 操作表示符(0  或   SEM_UNDO      或    IPC_NOWAIT)
};  (这样做应该是为了减少semop中的参数个数)

IPC_NOWAIT //When the operation of the signal cannot be satisfied, semop() will not block, and return immediately, and set the error message at the same time.
IPC_UNDO //When the program ends (whether normal or abnormal), the signal value is guaranteed to be reset to the value before the semop() call. The purpose of this is to avoid that the locked resource is not unlocked when the program ends abnormally, causing the resource to be locked forever.

  • nsops parameter: the number of sembuf structures in the array pointed to by sops (indicating the number of signals to be operated).
  • Return value: 0 is returned on success, and -1 is returned on failure.
semctl:int  semctl(int  semid,   int  semnum,   int   cmd,  .  .  . )
  • semid parameter: the semaphore identifier generated by semget.

  • semnum parameter: perform cmd operation on the semnumth signal in the signal set (starting from 0).

  • cmd arguments: semctl may have three or four arguments, depending on cmd.
    cmd:
    IPC_STAT reads the data structure semid_ds of a semaphore set and stores it in the buf parameter in semun.
    IPC_SET sets the element ipc_perm in the data structure semids of the semaphore set, and its value is taken from the buf parameter in semun.
    IPC_RMID deletes the semaphore set from the system
    GETALL is used to read the values ​​of all semaphores in the semaphore set, stored in the array of semnu
    SETALL sets the value of each member semval of the specified semaphore set
    GETPID returns the last execution The PID of the process the semop operates on.
    SETVAL sets the val data member to the current number of resources.
    GETVAL uses the current value in semval as the return of the function, that is, the number of existing resources. The return value is a non-negative number.

  • The fourth parameter: for a user-defined union:

union semun
{
    
    
       int val;                                  // cmd == SETVAL
       struct semid_ds *buf        // cmd == IPC_SET或者 cmd == IPC_STAT
       unsigned short *array;                  // cmd == SETALL,或 cmd = GETALL

       struct seminfo  *__buf;  // cmd == IPC_INFO只有在linux下才有。

};
  • Return value: -1 is returned in case of error, and the return value in case of success is the corresponding result according to the result of cmd.

Usage example:

#include <iostream>
#include <sys/types.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.h>

using namespace std;

union semun{
    
    
	int val;
};

void p_func(int id)
{
    
    
	struct sembuf sb;
	sb.sem_num = 0;
	sb.sem_op = -1;
	sb.sem_flg = 0;
	semop(id,&sb,1);
}
void v_func(int id)
{
    
    
	struct sembuf sb;
	sb.sem_num = 0;
	sb.sem_op = 1;
	sb.sem_flg = 0;
	semop(id,&sb,1);
}

int main(void)
{
    
    
	int Sem_id = semget(123,1,IPC_CREAT|0644);
	if(Sem_id  < 0)
	{
    
    
		cout << "semget failed" << endl;
		exit(1);

	}
	else
	{
    
    
		cout << "semget successed" << endl;
		union semun su;
		su.val = 5;
		cout << "before sem num:  " << semctl(Sem_id,0,GETVAL,0) << endl;
		semctl(Sem_id,0,SETVAL,su);
		cout << "after sem num: " << semctl(Sem_id,0,GETVAL,0) << endl;
		p_func(Sem_id);
		p_func(Sem_id);
		p_func(Sem_id);
		p_func(Sem_id);
		cout << "after sem num: " << semctl(Sem_id,0,GETVAL,0) << endl;

		v_func(Sem_id);
		cout << "after sem num: " << semctl(Sem_id,0,GETVAL,0) << endl;
		
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_68294039/article/details/127450804