Basic concept of process:
1. Processes and procedures
A program is an executable file stored on disk. The program is loaded into memory and starts running.
When a program is loaded multiple times, multiple processes are generated
A process is an active computer program
2. Classification of processes
Processes are generally divided into three types: interactive process, batch process and daemon process
When the system is in the active state, it is automatically started by the daemon process in the background
3. View process
Simple mode ps displays the process information of the current user's control terminal
List mode ps auxw displays all process details
a processes with control terminals for all users
x process without control terminal
u displays the details of the process
w is displayed with a larger column width
Owner of USER process
PID process number
%CPU utilization
%MEM kernel usage
Bytes used by VSZ virtual memory
Bytes used by RSS physical memory
TYY terminal equipment number? Indicates that there is no terminal control device
Status of STAT process
O ready, waiting to be dispatched
R is running, the Linux system does not have 0, and ready is also represented by R
S sleep that can be awakened, such as system interruption, obtaining resources and receiving signals, can wake it into running state
D sleep that cannot be awakened can only be awakened by the system
T suspended state: after receiving SIGSTOP signal, it enters the suspended state, and after receiving SIGCONT signal, it enters the running state
W waiting for memory paging (abandoned after 2.6 kernel)
Z ombie state
X death status
< high priority
N low priority
l multithreaded process
Leader of s process
L memory locked into memory
+ process group in background
The time when the START process started
TIME
COMMAND command to start the process
4. Parent process, child process, orphan process and zombie process
A process can be created by another process. The creator is called the parent process and the creator is called the child process. After the child process is started by the parent process, it will run at the same time under the call of the operating system
When the child process ends before the parent process, the child process will send a SIGCHLD signal to the parent process. At this time, the parent process should recycle the relevant resources of the child process. If not, the child process will become a zombie process
Zombie process: the process has died, but its parent process does not immediately recover its related resources, so the process enters the zombie state
Orphan process: the parent process ends before the child process, and the child process becomes an orphan process. At this time, the orphan process will be adopted by the orphanage (init daemon), and init is the parent process of the orphan process
5. Process identifier
Each process has a unique representation of a non negative integer representation, that is, its process ID/PID
The process ID is unique at any time, but it can be reused. Once the process is completed, its PID will be recycled by the system and can be reassigned to other newly created processes for use after a period of time (delayed reuse)
pid_t getpid(void); Function: get the process of the current process ID pid_t getppid(void); Function: get the parent process of the current process ID init Process of ID Always 1
Create process:
int system(const char *command);
Function: execute an executable file, which creates a child process
Return value: returns after the child process ends
The implementation of this function calls the fork and waitpid functions. In fact, it is equivalent to creating a sub process, which loads the executable command
pid_t fork(void);
Function: create sub process
Return value: return twice in a call. The child process returns 0. The parent process returns the ID of the child process. When the number of processes exceeds the system limit, the process creation fails and returns - 1
The child process created through fork will copy the parent process (data segment, bss segment, heap, stack, IO buffer) and other data areas, share the code segment with the parent process, and the child process will inherit the information processing method of the parent process
After the function is called, the parent and child processes run independently. It is uncertain who returns first, but you can determine which process executes first through sleep
for(;😉
{
fork(); // Will run out of resources
}
The parent process can enter different branches and execute different codes according to different return values
Creating a child process through fork can share the file descriptor of the parent process
Different ordinary processes cannot share file descriptors with the same value
pid_t vfork(void)
Function: create sub processes by loading executable files
Return value: the child process returns 0, and the parent process returns the PID of the child process
The child process returns first. At this time, the child process is not created successfully. You need to load an executable file to replace all the resources of the current child process. The child process that completes the replacement is created successfully, and the parent process can return
#include <stdio.h> #include <unistd.h> int main(int argc,const char* argv[]) { printf(".%d\n",getpid()); pid_t pid = fork(); if(0 == pid) { printf("I am a subprocess%u My parent process is %u\n",getpid(),getppid()); pause(); } else { printf("I am the parent process %u,My subprocess is %u\n",getpid(),pid); pause(); } }
Use the exec system function to load the executable file:
int execl(const char *path, const char *arg, ...); path: Path to executable arg: Generally, the first parameter on the command line is the name of the executable file. At least one parameter is NULL ending int execlp(const char *file, const char *arg, ...); file: The name of the executable file will be changed according to the environment variable PATH To find the executable int execle(const char *path, const char *arg, ..., char * const envp[]); envp: Environment variable table. The parent process can pass the environment variable table to the child process when loading the child process, so that the parent and child processes share one environment variable table int execv(const char *path, char *const argv[]); argv: Pointer array, which is composed of strings passed to child processes to NULL ending int execvp(const char *file, char *const argv[]); int execvpe(const char *file, char *const argv[], char *const envp[]);
Note: exec series functions will not return normally. When the loading sub process fails to load the executable file, it will return - 1
The child process created with exec series functions will not inherit the signal processing function of the parent process, but can inherit the signal mask of the parent process
Normal exit of process:
1. Execute return n in the main function, and the return value can be received by its parent process
2. The exit function is called, which is a standard library function
void exit(int status);
Function: calling this function at any time can end the process
Status: end status code, which has the same effect as the return value in the return function
Note: this function does not return
Before the process exits
int atexit(void (*function)(void)); Function: register the function to be executed before the end of a process int on_exit(void (*function)(int , void *), void *arg); Function: register the function to be executed before the end of a process int: return Value or exit Parameters of function arg: Will be automatically passed to at the end of the process function function call exit What will happen: 1,Call first and pass in advance atexit/on_exit If all registered functions are registered, the execution order is opposite to the registration order 2,Flush and close the standard in the open state IO flow 3,The implementation of this function calls_exit/_Exit
3. Call_ exit / _Exit function
void _exit(int status); Function: end the process, provided by the system void _Exit(int status); Function: end the process, provided by the standard library 1,Their parameters will be obtained by the parent process 2,All open file descriptors will be closed before the process ends(open) 3,Send to parent process SIGCHLD signal 4,The function also does not return
4. The last thread of the process executes the return statement
5. The last thread of the process executes pthread_exit function
Abnormal termination of process:
1. The process calls the abort function and generates the SIGABRT signal
2. The process can accept some signals, which can be sent by other processes, sent by itself, or caused by its own error
3. The last thread of the process received a cancel operation and responded to it
These three end methods cause the parent process to be unable to obtain the end status code, all of which are called abnormal termination
Note: no matter how the process ends, it will execute the same piece of code, close all open file descriptors and free all memory
whether
Recycling of child processes:
For any ending method, the parent process is expected to know how the child process ends and the ending status code through the wait and waitpid functions
#include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status); Function: wait for the end of the sub process and obtain the end status code Return value: child process PID 1,If all child processes are running, the function will block 2,If any child process ends, it will immediately return the end status code and PID 3,If there are no child processes, return immediately-1 WIFEXITED(status) Judge whether the subprocess ends normally. If so, return true WEXITSTATUS(status) If the subprocess ends normally, you can get the correct end status code, only Can get the lower eight bits WIFSIGNALED(status) Judge whether the subprocess ends normally. If so, return true WTERMSIG(status) Judge whether the subprocess is abnormally terminated, and you can obtain the signal code leading to the abnormal termination be careful: because wait The function may be blocked, so it is not suitable to call it in the business logic of the parent process. Therefore, you can use SIGCHID Signal processing function, which is called in the processing function wait Function. Note that you can get the status of the ending child process without affecting the normal business logic of the parent process pid_t waitpid(pid_t pid, int *status, int options); Function: specifies to recycle one or more processes pid: < -1 Waiting to belong abs(pid)The process in the process group with the number of ends -1 Wait for the end of any child process. The function is equivalent to wait 0 Wait for any process in the same group to end >0 wait for pid The process ends status: Process end status code, and wait Equivalence of options: 0 Blocking mode, equal to wait WNOHANG Non blocking mode, if no child process ends, return immediately WUNTRACED If a process is in a suspended state, the status code of the process is returned WCONTINUED If a process changes from suspended state to continue running, the status code of the process is returned WIFSTOPPED(status) Judge whether the process is in a suspended state. If yes, it returns true WSTOPSIG(status) Gets the signal that caused the process to pause WIFCONTINUED(STATUS)Judge whether the process changes from suspended state to running state. If yes, it returns true
Exercise: use today's knowledge to implement a system function
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <sys/wait.h> int _system(const char* command) { pid_t pid = vfork(); if(0 == pid) { return execlp(command,command,NULL); } else { int status = 0; waitpid(pid,&status,0); return status; } } int main(int argc,const char* argv[],char** environ) { _system("clear"); printf("-----------"); }
Interprocess communication:
Basic concepts:
What is interprocess communication:
It refers to the process of data interaction between two or more processes, because processes are independent of each other. In order to make multiple processes work together, they must interact with each other
Classification of interprocess communication: (required)
Simple interprocess communication: signals, files, environment variables, command line parameters
Traditional way of interprocess communication: pipeline file
XSI interprocess communication: shared memory, message queue, semaphore
Network interprocess communication: Socket socket local Socket file network TCP/IP
Traditional interprocess communication:
Pipeline is the oldest way of inter process communication in UNIX, which means that all systems support it. In the early days, the pipeline was half duplex, and now some systems have full duplex (but it should also be assumed that the pipeline is half duplex)
A pipe is a special file. Its data flows in the file and will disappear after reading. If there is no data in the file to read, it will be blocked
Famous pipeline:
Communication based on pipeline file with file name
Programming model
Process A process B
Create pipe
Open pipe open pipe
Write data read data
Close the pipe close the pipe
Delete pipe
To create a pipe file:
1,command mkfifo file 2,Function: int mkfifo(const char *pathname, mode_t mode); Functions: creating pipe files pathname: Pipeline file path mode: Pipeline file permissions 3,Standard library function FILE* popen(const char *command, const char *type); Function: open or create pipe files command: Executable file name type: r The file pointer links to the standard output of the executable w The file pointer links to the standard input of the executable file int pclose(FILE *stream); Function: close pipe file Note: special functions for closing pipeline files must not be associated with fclose Mixed use
// A #include <stdio.h> #include <string.h> #include <unistd.h> int main(int argc,const char* argv[]) { int fd[2] ={}; // Gets the fd array of anonymous pipes if(pipe(fd)) { perror("pipe"); return -1; } // Create child process if(fork()) { // Parent process Responsible for writing and closing reading close(fd[0]); for(;;) { char buf[256] = {}; printf(">>>"); scanf("%s",buf); write(fd[1],buf,strlen(buf)); if(0 == strcmp("quit",buf)) { printf("End of communication\n"); usleep(5000); break; } usleep(5000); } close(fd[1]); } else { // The subprocess is responsible for reading and writing close(fd[1]); for(;;) { char buf[256] = {}; read(fd[0],buf,sizeof(buf)); printf("read:%s\n",buf); if(0 == strcmp(buf,"quit")) { printf("End of communication\n"); break; } } close(fd[0]); } }
// B #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> int main(int argc,const char* argv[]) { //Open pipe file int fd = open("fifo",O_RDONLY); if(0 > fd) { perror("open"); return -1; } //Read data for(;;) { char buf[256] = {}; read(fd,buf,sizeof(buf)); printf("read:%s\n",buf); if(0 == strcmp(buf,"quit")) { printf("End of communication!\n"); break; } } //Close pipe file close(fd); }
Anonymous pipeline:
Note: it is only suitable for use between parent and child processes created through the fork function
Programming model
Parent process and child process
Create and get a pair of fd
Create a child process and copy a pair of fd
Turn off read and write
Write data read data
Turn off write and turn off read
int pipe(int pipefd[2]); Function: create an anonymous pipeline file, pipefd: For storing pipe files fd Array of pipefd[0]:For reading pipefd[1]:For writing
#include <stdio.h> #include <string.h> #include <unistd.h> int main(int argc,const char* argv[]) { int fd[2] ={}; // Gets the fd array of anonymous pipes if(pipe(fd)) { perror("pipe"); return -1; } // Create child process if(fork()) { // Parent process Responsible for writing and closing reading close(fd[0]); for(;;) { char buf[256] = {}; printf(">>>"); scanf("%s",buf); write(fd[1],buf,strlen(buf)); if(0 == strcmp("quit",buf)) { printf("End of communication\n"); usleep(5000); break; } usleep(5000); } close(fd[1]); } else { // The subprocess is responsible for reading and writing close(fd[1]); for(;;) { char buf[256] = {}; read(fd[0],buf,sizeof(buf)); printf("read:%s\n",buf); if(0 == strcmp(buf,"quit")) { printf("End of communication\n"); break; } } close(fd[0]); } }
XSI interprocess communication:
System interface for interprocess communication executed by X/open company
XSI interprocess communication requires the help of the system kernel, and the kernel object needs to be created. The kernel object is returned to the user in the form of an integer, which is equivalent to a file descriptor, also known as IPC identifier
The file name is required for the creation and opening of files, and the IPC key value (integer) is also required for the creation of IPC kernel objects. It must be ensured that the IPC key value is unique
#include <sys/types.h> #include <sys/ipc.h> key_t ftok(const char *pathname, int proj_id); Function: calculate a unique IPC Key value pathname: The project path is not calculated by characters, but by the location of the path. If the provided path is a false path, it may be calculated by accounting IPC Key value proj_id: Item No Return value: calculated IPC Key value
Shared memory:
Basic features:
Two or more processes share a piece of memory managed and maintained by the kernel, which can be mapped with the virtual memory space of the process
Advantages: it does not need to copy information and is the fastest IPC mechanism
Disadvantages: synchronous access needs to be considered
#include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); Function: create\Get shared memory key: Unique information provided by the process IPC Key value size: The size of shared memory. When obtaining shared memory, this parameter is meaningless and is generally set to 0 shmflg: IPC_CREAT Create shared memory IPC_EXCL Error returned when shared memory already exists Assign 0 when getting mode_flags: Permissions are required to create shared memory Return value: IPC Identifier, error return-1 void *shmat(int shmid, const void *shmaddr, int shmflg); Function: mapping between virtual memory and shared memory shmid: IPC Identifier, shmget Return value of shmaddr: The virtual memory address you want to map. Here you are NULL The system will operate automatically shmflg: SHM_RDONLY: Access shared memory as read-only Return value: the first address of the virtual memory mapped with the shared memory. Failure is returned(void *) -1 int sgmdt(const void *shmaddr); Function: unmap shmaddr: Mapped virtual memory address int shmctl(int shmid, int cmd, struct shmid_ds *buf); Function: delete/Control shared memory shmid: IPC identifier cmd: IPC_STAT Get shared memory properties be buf It is an output parameter IPC_SET Set shared memory properties be buf It is an input parameter IPC_RMID Delete shared memory NULL struct shmid_ds { struct ipc_perm shm_perm; //Information about the owner size_t shm_segsz; //Shared memory bytes time_t shm_atime; //Last mapping time time_t shm_dtime; //Last unmapping time time_t shm_ctime; //Last change time pid_t shm_cpid; //Creator process number pid_t shm_lpid; //Last mapped \ unmapped process number shmatt_t shm_nattch; //Current mapping times ... }; struct ipc_perm { key_t __key; //Create PIC key value of shared memory uid_t uid; //User ID currently using shared memory gid_t gid; //User group ID currently using shared memory uid_t cuid; //User ID to create shared memory gid_t cgid; //User group ID to create shared memory unsigned short mode; //Shared memory permissions unsigned short __seq; //Serial number of shared memory };
Programming model
Process A process B
Create shared memory get shared memory
Map shared memory map shared memory
Notify read after writing data read after receiving read notification
Read data after receiving read notification and notify read after writing data
Unmapping unmapping
Delete shared memory
// Process A #include <stdio.h> #include <stdlib.h> #include <sys/shm.h> #include <sys/ipc.h> #include <unistd.h> #include <sys/types.h> #include <signal.h> #include <string.h> int shmid; char* shm; //After receiving the read message, the signal processing function is responsible for reading data from the shared memory void sigrtmin(int num) { // Receive read messages and read data printf("read:%s\n",shm); if(0 == strcmp("quit",shm)) { printf("End of communication\n"); //Unmap if(shmdt(shm)) { perror("shmdt"); exit(-1); } usleep(1000);//Wait for the opposite process to unmap //Delete shared memory if(shmctl(shmid,IPC_RMID,NULL)) { perror("shmctl"); exit(-1); } } } int main(int argc,const char* argv[]) { // Register signal processing function signal(SIGRTMIN,sigrtmin); printf("I am the process%u\n",getpid()); pid_t pid = 0; printf("Please enter the process of communicating with me PID:"); scanf("%u",&pid); // Create shared memory shmid = shmget(ftok(".",110),4096,IPC_CREAT|0644); if(0 > shmid) { perror("shmget"); return -1; } // Map shared memory shm = shmat(shmid,NULL,0); if(shm == (void*)-1) { perror("shmat"); return -1; } // Write data and notify other processes for(;;) { printf(">>>"); scanf("%s",shm); kill(pid,SIGRTMIN); if(0 == strcmp(shm,"quit")) { printf("End of communication\n"); break; } } // Unmap if(shmdt(shm)) { perror("shmdt"); return -1; } usleep(1000);//Wait for the opposite process to unmap //Delete shared memory if(shmctl(shmid,IPC_RMID,NULL)) { perror("shmctl"); return -1; } }
// Process B #include <stdio.h> #include <stdlib.h> #include <sys/shm.h> #include <sys/ipc.h> #include <unistd.h> #include <sys/types.h> #include <signal.h> #include <string.h> char* shm; //After receiving the read message, the signal processing function is responsible for reading data from the shared memory void sigrtmin(int num) { // Receive read messages and read data printf("read:%s\n",shm); if(0 == strcmp("quit",shm)) { printf("End of communication\n"); //Unmap if(shmdt(shm)) { perror("shmdt"); exit(-1); } exit(0);//quti has been received. You need to end the whole program } } int main(int argc,const char* argv[]) { // Register signal processing function signal(SIGRTMIN,sigrtmin); printf("I am the process%u\n",getpid()); pid_t pid = 0; printf("Please enter the process of communicating with me PID:"); scanf("%u",&pid); // Get shared memory int shmid = shmget(ftok(".",110),0,0); if(0 > shmid) { perror("shmget"); return -1; } // Map shared memory shm = shmat(shmid,NULL,0); if(shm == (void*)-1) { perror("shmat"); return -1; } // Write data and notify other processes for(;;) { printf(">>>"); scanf("%s",shm); kill(pid,SIGRTMIN); if(0 == strcmp(shm,"quit")) { printf("End of communication\n"); break; } } // Unmap if(shmdt(shm)) { perror("shmdt"); return -1; } }
Message queue:
Basic features: it is a data linked list managed and maintained by the kernel, which sends and receives data through message types.
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgget(key_t key, int msgflg); Function: create\Get message queue key: IPC Key value msgflg: IPC_CREAT Create message queue IPC_EXCL If the message queue already exists, an error is returned If get message queue Directly to 0 If you are creating a message queue, remember to provide permissions mode Return value: returned successfully IPC Identifier, error return-1 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); Function: send data to message list msqid: IPC identifier msgp: The first address of the message to send struct msgbuf { long mtype; // Message type char mtext[n]; // data }; msgsz: The number of bytes of data, excluding the message type msgfl: Blocking general write 0 IPC_NOWAIT When the message queue is full, do not wait to return immediately ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg); Function: read data from message queue msqid: IPC identifier msgp: First address of stored data msgsz: The maximum number of bytes of data in the structure msgtyp: Message type 0 Read the first message in the message queue >0 Read the message type in the message queue equal to msgtyp News of <0 Read message type is less than abs(msgtyp)Message, if more than one, the smallest message is read msgflg: IPC_NOWAIT When there is no matching message type in the message queue, it returns immediately MSG_EXCEPT If msgtyp>0,The first message type read is not msgtyp News of MSG_NOERROR If this flag is included, read msgsz Bytes. If this flag is not included, the actual length of the message>msgsz,An error is returned without reading the data. Return value: the number of bytes successfully read int msgctl(int msqid, int cmd, struct msqid_ds *buf); Function: delete\Get properties of message queue msqid: IPC identifier cmd: IPC_STAT Get properties of information queue IPC_SET Set properties of message queue IPC_RMID Delete message queue buf: struct msqid_ds { struct ipc_perm msg_perm; // Owner information time_t msg_stime; // Last sending time time_t msg_rtime; // Last receiving time time_t msg_ctime; // Last modification time unsigned long __msg_cbytes; // Bytes of the current message queue msgqnum_t msg_qnum; // Number of messages in the current message queue msglen_t msg_qbytes; // The maximum number of bytes of a message in the queue pid_t msg_lspid; // Last sender's PID pid_t msg_lrpid; // PID of last receiver };
Programming model
Process A process B
Create message queue get message queue
Send message receive message
Receive message send message
Delete message queue
// Process A #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include "messgeage.h" int main(int argc,const char* argv[]) { // Create message queue int msgid = msgget(ftok(".",120),IPC_CREAT|0644); if(0 > msgid) { perror("msgget"); return -1; } Msg msg = {}; for(;;) { msg.type = 5; printf(">>>"); scanf("%s",msg.data); //send message if(msgsnd(msgid,&msg,strlen(msg.data)+1,0)) { perror("msgsnd"); break; } if(0 == strcmp("quit",msg.data)) break; //receive messages if(0 == msgrcv(msgid,&msg,MESMAX,6,0)) { perror("msgrcv"); break; } printf("recv:%s\n",msg.data); if(0 == strcmp("quit",msg.data)) break; } printf("End of communication!\n"); usleep(1000); // Delete message queue if(msgctl(msgid,IPC_RMID,NULL)) { perror("msgctl"); return -1; } return 0; }
// Process B #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include "messgeage.h" int main(int argc,const char* argv[]) { // Get message queue int msgid = msgget(ftok(".",120),0); if(0 > msgid) { perror("msgget"); return -1; } Msg msg = {}; for(;;) { //receive messages if(0 == msgrcv(msgid,&msg,MESMAX,5,0)) { perror("msgrcv"); break; } printf("recv:%s\n",msg.data); if(0 == strcmp("quit",msg.data)) break; msg.type = 6; printf(">>>"); scanf("%s",msg.data); //send message if(msgsnd(msgid,&msg,strlen(msg.data)+1,0)) { perror("msgsnd"); break; } if(0 == strcmp("quit",msg.data)) break; } printf("End of communication!\n"); return 0; }
Amount of information:
Basic features: a "global variable" maintained by kernel sharing, which is used to record the number of shared resources and limit the process's access to resources
1. If the value of the variable is greater than 0, the resource can be used. At this time, the variable value needs to be - 1 before the resource can be used
2. If the value of the variable is equal to 0, it indicates that the available resources can be used. At this time, the process will enter sleep until the variable is greater than 0, and the process will be awakened. Execute step 1
3. When the resource is used up, the value of the variable is + 1, and the dormant process can be awakened
#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget(key_t key, int nsems, int semflg); Function: create or obtain information volume key: IPC Key value nsems: The number of semaphores is generally written as 1 semflg: IPC_CREAT Create semaphore IPC_EXCL Return if present-1 mode: jurisdiction Return value: IPC identifier Failure Return-1 int semop(int semid, struct sembuf *sops, unsigned nsops); Function: add and subtract semaphores semid: IPC identifier sops: struct sembuf { unsigned short sem_num; // Semaphore subscript short sem_op; 1 Semaphore+1 0 The value of the waiting semaphore is 0 >0 Semaphore-1,If not-1,Then blocking short sem_flg; IPC_NOWAIT No blocking SEM_UNDO If the semaphore is not restored after the process is terminated, the system will restore it automatically } nsops: express sops How many structures does the pointer point to? Usually write 1 int semctl(int semid, int semnum, int cmd, ...); Function: delete/Control semaphore semid: IPC identifier semnum: Semaphore subscript cmd: IPC_STAT Get shared memory properties IPC_SET Set shared memory properties IPC_RMID Delete shared memory GETALL Get the values of all semaphores GETVAL Gets the value of a semaphore GETNCNT Gets the number of all processes waiting for subtraction SETALL Set the values of all semaphores SETVAL Set the value of a semaphore union semun { int val; // Used to set the value of the semaphore struct semid_ds *buf; // Properties of semaphores unsigned short *array; // Get / set the value of semaphore in batch };
Donkey riding
#include <stdio.h> #include <sys/wait.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/types.h> int main(int argc,const char* argv[]) { // Create semaphore int semid = semget(ftok(".",119),1,IPC_CREAT|0644); if(0 > semid) { perror("semget"); return -1; } // Sets the value of the semaphore if(semctl(semid,0,SETVAL,5)) { perror("semctl"); return -1; } // printf("%d\n",semctl(semid,0,GETVAL)); printf("I am the process%u,I have%d A little donkey\n",getpid(),semctl(semid,0,GETVAL)); // Ten processes compete for five resources for(int i=0; i<10; i++) { pid_t pid = fork(); if(0 == pid) { struct sembuf buf = {0,-1,0}; semop(semid,&buf,1); printf("I am a subprocess%u,I rode a little donkey,also%d A little donkey\n",getpid(),semctl(semid,0,GETVAL)); sleep(i); buf.sem_op = 1; semop(semid,&buf,1); printf("I am a subprocess%u,I also bought a little donkey,also%d A little donkey\n",getpid(),semctl(semid,0,GETVAL)); return 0; } } while(-1 !=wait(NULL)); printf("I am the process%u,I have%d A little donkey\n",getpid(),semctl(semid,0,GETVAL)); if(semctl(semid,0,IPC_RMID)) { perror("semctl"); return -1; } }