In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)06/02 Report--
Last time we talked about solving the concurrency problem, semaphores are needed. Next, a brief review.
Semaphore
A semaphore is a variable that can only take positive integer values, and only two operations can be performed on these positive integers: wait and signal. (in my understanding, semaphores are designed to access some critical resources.)
These two operations of semaphores are represented by two tokens:
P (semaphore variable) stands for waiting (requesting resources)
V (semaphore variable) stands for signal (release of resources)
The simplest classification of semaphores is a variable that can only take values of "0" and "1", which is often called "binary semaphore".
A semaphore that can take multiple positive integer values is called a general semaphore.
P, V operation
Suppose we have a signal variable sv, then the definition of the pv operation is as follows
P (sv): if the value of sv is greater than zero, subtract 1 from it; if the value of sv is equal to zero, suspend the execution of the process
V (sv): if another process is suspended while waiting for the sv variable, let it resume execution; if no process is suspended because it is waiting for the sv variable, add 1 to it
Semaphore function
The functions to be used are as follows:
# include
< sys/types.h># include
< sys/ipc.h># include
< sys/sem.h>Int semget (key_t key, int nsems, int semflg)
Function: create a new semaphore or get an existing semaphore keyword
Key: is an integer value through which unrelated processes will access the same semaphore
Num_sems: the number of semaphores to be used, which almost always takes a value of 1
Sem_flags: a group of flags whose function is similar to the various flags of the open function. The lower nine bits of the semaphore are the permissions of the semaphore, and its function is equivalent to the access permission of the file. You can do bit-by-bit OR operation with the key value IPC_CREATE to create a new semaphore.
If successful, a positive value will be returned, which is the identification code to be used by other semaphore functions. If it fails, it will return-1.
Int semop (int semid, struct sembuf * sops, unsigned nsops)
Function: change the key value of the semaphore (which is used to perform PV operations)
Semid: the identification code of the semaphore, that is, the return value of the semget function
Sops: a pointer to a structure value
Nsop: the number of operation semaphores, that is, the number of sops structure variables, should be greater than or equal to 1. The most common setting is that this value is equal to 1, and only one semaphore can be operated.
All actions called by Semop are done at once to avoid possible competition due to the use of multiple semaphores.
The structure of sembuf is as follows:
Sem_num is the number of semaphores. If you do not need to use a set of semaphores for your work, this value is usually 0.
Sem_op is the value added or subtracted by a semaphore during a PV operation. Generally speaking, only two values are used, one is "- 1", that is, P operation, waiting for the semaphore to become available, and the other is "+ 1", that is, our V operation, emitting semaphore has become available.
Sem_flag is usually set to SEM_UNDO. She will make the operating system track the current process's modifications to the semaphore
Int semctl (int semid, int semnum, int cmd,...)
Sem_id: is a semaphore identification code returned by the semget function
Sem_num: the number of a semaphore, which is used if you need to use a grouped semaphore in your work; it usually takes a value of 0, indicating that this is the first and only semaphore.
Comman: the action to be taken
If there is a fourth parameter, it will be a "union semun" compound structure.
First of all, let's talk about cmd. There are the following:
Among them, the more commonly used are the following two:
SETVAL: used to initialize the semaphore to a known value, which is passed as a val member in the semun structure.
IPC_RMID: delete a semaphore identification code that is no longer used.
Let's talk about the fourth parameter, this function is special, when there are four parameters, it is a "union semun" compound structure. (it may not be in the header file, it is best to redefine it yourself.)
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) * /}; case study
Do a little exercise and take a car rental example.
A total of 5 factories, each factory has the number of cars: 37 506. Consider car rental (access to critical resources)
Factory.c:
# include
< stdio.h># include
< sys/types.h># include
< sys/ipc.h># include
< sys/sem.h>/ * example there are 5 factories for car rental. Each factory has the number of cars: 37 506 = > the number of semaphores = 5, the values of semaphores are: 37 506, and the semaphore number starts with 0 * / 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) * /}; int main () {int i; int sem_id; int values [5] = {3LECO); union semun value = {0}; / / create semaphore sem_id = semget If (sem_id! =-1) {for (I = 0; I)
< 5;i++) { semctl(sem_id , i , IPC_RMID); } }sem_id = semget(1000,5,IPC_CREAT);printf("%d\n",sem_id);if(sem_id == -1){ perror("producer semget"); return -1;}//设置信号量for(i = 0 ; i < 5 ; i++){ printf("%d ",semctl(sem_id,i,GETVAL));}printf("\n");for(i = 0 ;i < 5; i++){ value.val = values[i]; //打印信号量 semctl(sem_id,i,SETVAL,value.val);}for(i = 0 ; i < 5 ; i++){ printf("%d ",semctl(sem_id,i,GETVAL));}return 0;} client.c: #include < stdio.h># include
< sys/types.h># include
< sys/ipc.h># include
< sys/sem.h>/ * struct sembuf {unsigned short sem_num; / / semaphore number short sem_op; / / semaphore operation short sem_flg; / / operation flags Flags recognized in sem_flg are IPC_NOWAIT and SEM_UNDO. * / int main () {int sem_id; struct sembuf buf = {0}; / / Open semaphore sem_id = semget (1000 sem_id 5); if (sem_id =-1) {perror ("consumer semget"); return-1;} printf ("waiting...\ n"); / / borrow a car buf.sem_num = 0 / / semaphore number buf.sem_op =-1; / request resource buf.sem_flg = SEM_UNDO; / / automatically release semop (sem_id,&buf,1); / / the third parameter must be 1 printf ("get a car.\ n"); / / borrowing sleep (20); / / return buf.sem_op = + 1; / / release resource semop (sem_id,&buf,1) Printf ("back a car.\ n"); return 0;}
Running result:
When the third client is executed, it waits until the first car is returned.
Producer and consumer problems
Learn the most classic questions about semaphores, all of which can be used to practice. The producer-consumer problem, the reader-writer problem, the philosopher dining problem and so on are all the same.
Requirements: the initial quantity of the product is 0, the producer is responsible for production, that is, + 1, and the consumer is responsible for consumption, that is-1. The warehouse can only store up to 10 products.
Here is the code for the producer-consumer problem:
(I use two semaphores. Usually one semaphore is used in the textbook. You can try it yourself.)
Public.c:
# ifndef _ PUBLIC_H_#define _ PUBLIC_H_#include
< stdio.h># include
< sys/types.h># include
< sys/ipc.h># include
< sys/sem.h>Unsigned short values [2] = {10SETALL 0}; 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) * /}; # endif
Producer
# include "public.h" / / semaphore: control inter-process synchronization problems, common resources, the number of resources (semaphore value) > = 0. / / P wait / request-1 Magi V signal / release, + 1//semget (create, open)\ semctl (delete, initialize), semop (PV) int main () {int semid;// two semaphores, one production, initialization 10, one consumption, initialization to 0 prime / production of a commodity, producer (zero semaphore-1), consumer (first semaphore + 1) / / unsigned short values [2] = {10pm 0} Union semun sem = {0}; struct sembuf buf1 = {0}; struct sembuf buf2 = {0}; / / 1. Create semaphores: semid = semget (1000 semget open 0); if (semid = =-1) {semid = semget; if (semid = =-1) {perror ("semget open."); return 1;}} / / 2. Semaphore initialization sem.array = values;semctl (semid,0,SETALL,sem); / / 3.pv operation while (1) {/ / production, semaphore [0] minus 1 buf1 buf1.sem_num = 0; buf1.sem_op =-1; buf1.sem_flg = SEM_UNDO;// printf ("can produce?\ n"); semop (semid,&buf1,1) / / the last parameter, as long as it is > 0, is OK / / printf ("yes.\ n"); sleep (1); / / after a product is produced, semaphore [1] plus 1 buf2 buf2.sem_num = 1; buf2.sem_op = + 1; buf2.sem_flg = SEM_UNDO; semop (semid,&buf2,1); printf ("finish produce.now:% d\ n", values [1]) / / printf ("all product:% d\ n", sem.array [1]);} return 0;}
Consumer
# include "public.h" int main () {int semid; struct sembuf buf1 = {0}; struct sembuf buf2 = {0}; semid = semget (1000 perror 0); if (semid = =-1) {perror ("semget open"); return 1;} / responsible for consuming while (1) {/ / whether semaphore [1] can be consumed Buf2.sem_op =-1; buf2.sem_flg = SEM_UNDO; semop (semid,&buf2,1); / / consumption sleep (3); / / semaphore [0] buf1 buf1.sem_num = 0; buf1.sem_op = + 1; buf1.sem_flg = SEM_UNDO; semop (semid,&buf1,1) Printf ("consume one product.\ n");}}
Running result:
Run. / producer first. When 10 products are produced, it will be blocked. At this time, run. / consumer, take a product every 3 seconds, and the producer will produce a product after 1 second.
Instant messaging Mini Program
Now, we can continue with our Mini Program. With the above two exercises, it is easier to understand. It is very similar to the problem of producers and consumers.
We set up two semaphores for reading and writing, one to control reading and one to control writing. The write semaphore is initialized to 1, and after writing-1, it becomes 0. The read semaphore is initialized to 0 and becomes the number of online users-1 after the write operation. If all users have finished reading, the read semaphore is 0 and the write semaphore is 1.
Public.h:
# ifndef _ PUBLIC_H_#define _ PUBLIC_H_#include
< stdio.h># include
< string.h># include
< sys/types.h># include
< sys/ipc.h># include
< sys/msg.h># include
< sys/shm.h># include
< signal.h># include
< sys/sem.h># include
< string># include
< map># include
< iostream>Using namespace std;// user information structure typedef struct user_t {USER_T user; char acMsg [10]; / / followed by user name identity, password authentication} USER_T;// login message queue structure typedef struct login_msg_t {long type; USER_T user;} LMSG_T;// chat message structure typedef struct msg_t {USER_T user; char acMsg [100];} MSG_T / / message queue: user login # define LOGIN_TYPE 1#define EXIT_TYPE 2#define MSG_KEY 1000#define MSG_SIZE sizeof (LMSG_T)-sizeof (long) / / shared memory: user list (free block: 0-idle 1-occupied) # define SHM_USER_KEY 1001#define MAX_USER 100#define SHM_USER_SIZE MAX_USER + MAX_USER * sizeof (USER_T) / / shared memory: chat # define SHM_MSG_KEY 1002#define SHM_MSG_SIZE sizeof (MSG_T) / / signal: update user list Read message # define SIGNAL_USERS 34#define SIGNAL_CHAT 35 / read / write semaphore # define SEM_KEY 1003union 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) * /} / / two semaphores, one control read, one control write / write semaphore initialized to 1, after writing-1, it becomes zero struct sembuf buf2 / read semaphore initializes to 0, and after write operation, it becomes the number of online users-1 picket / if all users have finished reading, the read semaphore is 0 and the write semaphore is 1union semun sem = {0}; struct sembuf buf1 = {0}; / / write struct sembuf buf2 = {0}; / / read # semaphore
Server.cpp:
# include "public.h" int main () {int msg_id; int shm_id; LMSG_T loginMsg = {0}; char * userAddr; USER_T * pUser; / / address actually written by the user map userMap; / / user list map::iterator it; int i; / * 1, create message queue: user login * / msg_id = msgget (MSG_KEY,0) If (msg_id = =-1) {msg_id = msgget (MSG_KEY,IPC_CREAT); if (msg_id = =-1) {perror ("server msgget"); return-1;}} / * 2, create shared memory: user list * / shm_id = shmget (SHM_USER_KEY,0,0) If (shm_id! =-1) {/ / already exists, delete shmctl (shm_id,IPC_RMID,NULL);} shm_id = shmget (SHM_USER_KEY,SHM_USER_SIZE,IPC_CREAT); userAddr = (char *) shmat (shm_id,NULL,0); / / Mapping pUser = (USER_T *) (userAddr + MAX_USER); memset (userAddr,0,SHM_USER_SIZE) / / initialize / * 3, create shared memory: chat message * / int shm_msg_id = shmget (SHM_MSG_KEY,0,0); if (shm_msg_id! =-1) {shmctl (shm_msg_id,IPC_RMID,NULL);} shm_msg_id = shmget (SHM_MSG_KEY,SHM_MSG_SIZE,IPC_CREAT) Char * msgAddr = (char *) shmat (shm_msg_id,NULL,0); memset (msgAddr,0,SHM_MSG_SIZE); / * 4. Create semaphore * / int sem_id; sem_id = semget (SEM_KEY,0,0); if (sem_id! =-1) {semctl (sem_id,0,IPC_RMID); semctl (sem_id,1,IPC_RMID) } sem_id = semget (SEM_KEY,2,IPC_CREAT); / / initialization semaphore value sem.val = 1; semctl (sem_id,0,SETVAL,sem); / / write sem.val = 0; semctl (sem_id,1,SETVAL,sem) / / read / / listen all the time to see if any user is online while (1) {memset (& loginMsg,0,sizeof (LMSG_T)); msgrcv (msg_id,&loginMsg,MSG_SIZE,0,0); / / any message will receive switch (loginMsg.type) {case LOGIN_TYPE: / / log in to cout
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.