1. Thread Synchronization - Semaphore
Semaphore is essentially a non negative integer counter, which is usually used to control access to public resources.
When the available public resources increase, call the function sem_post() increases the semaphore. Only when the semaphore value is greater than 0, the function sem_wait() can be returned, and the semaphore value is reduced by 1. When the semaphore is equal to 0, sem_wait() will be blocked until the semaphore value is greater than 0. Function sem_trywait() is the function sem_ The non blocking version of wait ().
2. Semaphore is the PV primitive used in the operating system. It is widely used for synchronization and mutual exclusion between processes or threads.
Semaphore is essentially a non negative integer counter, which is used to control access to public resources.
Working principle of PV primitive: PV primitive is an operation on semaphore sem of integer counter. One P operation makes sem minus one, while one V operation makes sem plus one. The process (or thread) determines whether it has access to public resources according to the semaphore value. When the semaphore sem value is greater than or equal to zero, the process (or thread) has access to public resources; On the contrary, when the semaphore sem value is less than zero, the process (or thread) will block until the semaphore sem value is greater than or equal to 0.
3.sem_init is used to create an anonymous semaphore and initialize its value
Header file: # include<semaphore. h>
Prototype: int sem_init(sem_t *sem,int pshared,unsigned int value);
Parameter: sem: semaphore pshared: determines whether semaphores can be shared among several processes. Since Linux has not yet implemented inter process semaphore sharing, this value can only be taken as 0 value: semaphore initialization value
Return value: Success: 0 Error: - 1
4.sem_getvalue -- get the semaphore value
Header file: # include<semaphore. h>
Prototype: int sem_getvalue(sem_t *sem,int * val);
Parameters: sem is the pointer to the semaphore, val is used to store the queried semaphore value
Return value: 0 for success, - 1 for failure
5.sem_destroy -- Clear semaphore
Header file: # include<semaphore. h>
Prototype: int sem_destroy (sem_t * sem);
Parameter: sem is the pointer to the semaphore
Return value: 0 for success, - 1 for failure
6.sem_wait - wait for shared resources (- 1 function)
sem_trywait -- wait for shared resources
Parameter: return value of sem pointer to semaphore: 0 if successful, - 1 otherwise.
Function supplement: sem can be used_ Wait to apply for shared resources, sem_ The wait function can test the value of the specified semaphore. If the value is greater than 0, it is subtracted by 1 and returned immediately. We can use the shared resources applied for. If the value is equal to 0, the calling thread will be put into sleep until the value becomes greater than 0. At this time, reduce it by 1, and the function will return later. sem_ The wait operation must be atomic.
sem_wait and sem_ The difference between trywait: sem_wait and sem_trywait is equivalent to the P operation. Both of them can reduce the semaphore value by one. The difference between the two is that if the semaphore is less than zero,
sem_wait will block the process
And sem_trywait will return immediately
int sem_post(sem_t *sem); (+1 function)
7. Header file: # include<semaphore. h>
Function prototype: int sem_post(sem_t *sem);
Parameter: sem pointer to signal lamp
Return Value: 0 if successful, - 1 otherwise.
Function supplement: when a thread finishes using a semaphore, it should call sem_post to tell the system that the requested resources have been used up. This function and sem_ The wait function has the opposite function. It adds 1 to the value of the specified semaphore, and then wakes up any thread that is waiting for the semaphore value to become a positive number.
89.. Code:
/************************************************************************************************************************************************************************************************************************ *File name: *Author: She001 *Time: *edition: *effect: ****************************************************************************************************************************************************************************************************************************/ #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #include<stdbool.h> #include<time.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<errno.h> #include<sys/wait.h> #include<a.out.h> #include<signal.h> #include<stdarg.h> #include<sys/socket.h> #include<utime.h> #include<sys/utsname.h> #include<sys/times.h> #include<sys/un.h> #include<ctype.h> #include<dirent.h> #include<sys/time.h> #include<sys/resource.h> #include<syslog.h> #include<pthread.h> #include<semaphore. h> //Functions used by semaphores // 0. Usage of semaphore //1. Application semaphore //2. Initialize semaphore //3.p Operation - 1 Operation //4. Read/write operation //5. v operation+1 operation //6. Destroy semaphores // int main(int argc,char *argv[]) { //1. Application semaphore sem_t sem; //2. Initialize semaphore if(sem_init(&sem,0,1)<0) //Light on { perror("sem_init error\n"); return -1; } else { printf("sem_init ok\n"); } //View semaphores int value =0; sem_getvalue(&sem,&value); printf("1 value = %d\n",value); //3.p Operation - 1 Operation sem_wait(&sem); //Light off operation (blocking version) sem_getvalue(&sem,&value); printf("2 value = %d\n",value); int s=sem_post(&sem); //Light on operation if(s<0) { perror("sem_post error\n"); } else { printf("sem_post ok\n"); } while(sem_trywait(&sem)) //Light on operation of non blocking version { perror("sem_trywait error\n"); sleep(1); } //4. Read/write operation printf("do something to resourme\n"); //5. v operation+1 operation s=sem_post(&sem); //Light on operation if(s<0) { perror("sem_post error\n"); } else { printf("sem_post ok\n"); } sem_getvalue(&sem,&value); printf("3 value = %d\n",value); //6. Destroy semaphores sem_destroy(&sem); return 0; }
9. Program function: apply the semaphore method to threads
code:
/************************************************************************************************************************************************************************************************************************ *File name: *Author: She001 *Time: *edition: *effect: ****************************************************************************************************************************************************************************************************************************/ #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #include<stdbool.h> #include<time.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<errno.h> #include<sys/wait.h> #include<a.out.h> #include<signal.h> #include<stdarg.h> #include<sys/socket.h> #include<utime.h> #include<sys/utsname.h> #include<sys/times.h> #include<sys/un.h> #include<ctype.h> #include<dirent.h> #include<sys/time.h> #include<sys/resource.h> #include<syslog.h> #include<pthread.h> #include<semaphore. h> //Functions used by semaphores // 0. Usage of semaphore //1. Application semaphore //2. Initialize semaphore //3.p Operation - 1 Operation //4. Read/write operation //5. v operation+1 operation //6. Destroy semaphores // int num=100; //1. Application semaphore (global variable) sem_t sem; void * pthread_fun1(void *arg)//Function to create thread { while(sem_trywait(&sem)) //Operation of turning off the light without blocking the board { perror("fun1 sem_trywait error\n"); sleep(1); } printf("this is %s %d %ld start \n",__func__,getpid(),pthread_self()); for(int i=0;i<5;i++) { num+=1; printf("1111111 :%d\n",num); sleep(1); } printf("this is %s %d %ld end \n",__func__,getpid(),pthread_self()); int s=sem_post(&sem); //Light on operation if(s<0) { perror("sem_post error\n"); } else { printf("sem_post ok\n"); } } void * pthread_fun2(void *arg)//Function to create thread { while(sem_trywait(&sem)) //Operation of turning off the light without blocking the board { perror("fun2 sem_trywait error\n"); sleep(1); } printf("this is %s %d %ld start \n",__func__,getpid(),pthread_self()); for(int i=0;i<5;i++) { num-=2; printf("22222222 :%d \n",num); sleep(1); } printf("this is %s %d %ld end \n",__func__,getpid(),pthread_self()); int s=sem_post(&sem); //Light on operation if(s<0) { perror("sem_post error\n"); } else { printf("sem_post ok\n"); } } void * pthread_fun3(void *arg)//Function to create thread { while(sem_trywait(&sem)) //Operation of turning off the light without blocking the board { perror("fun3 sem_trywait error\n"); sleep(1); } printf("this is %s %d %ld start \n",__func__,getpid(),pthread_self()); for(int i=0;i<5;i++) { num+=3; printf("333333333 :%d\n",num); sleep(1); } printf("this is %s %d %ld end \n",__func__,getpid(),pthread_self()); int s=sem_post(&sem); //Light on operation if(s<0) { perror("sem_post error\n"); } else { printf("sem_post ok\n"); } } int main(int argc,char *argv[]) { //2. Initialize semaphore if(sem_init(&sem,0,1)<0) //Light on { perror("sem_init error\n"); return -1; } else { printf("sem_init ok\n"); } //View semaphores //Create thread int value =0; sem_getvalue(&sem,&value); printf("1 value = %d\n",value); pthread_t tid1 =0; pthread_t tid2 =0; pthread_t tid3 =0; pthread_create(&tid1,NULL,pthread_fun1,NULL); pthread_create(&tid2,NULL,pthread_fun2,NULL); pthread_create(&tid3,NULL,pthread_fun3,NULL); pthread_join(tid1,NULL); //Do not accept exit status of child thread pthread_join(tid2,NULL); //Do not accept exit status of child thread pthread_join(tid3,NULL); //Do not accept exit status of child thread //6. Destroy semaphores sem_destroy(&sem); return 0; }
10. Introduction to signal:
1. Signal definition: signal: a method of transmitting messages between processes. The full name of signal is soft interrupt signal, also called soft interrupt. Signals are used to notify the process that an asynchronous event has occurred. There are two sources of signal events: 1. Hardware sources, such as we pressed the keyboard or other hardware failures; 2. Software source. The most commonly used signal related system functions are kill(), raise(), alarm() and setimer (). The software source also includes some illegal operations. Note: The signal is only used to inform a process of what has happened, and does not pass any data to the process.
2 Signal processing by process
A process can respond to and process a signal in three ways: 1. Ignore a signal: ignore a signal and do nothing with it, as if it had never happened. 2 Capture signal: It is a similar interrupt processing program. For the signal to be processed, the process can specify a processing function to be processed by this function// Programming. 3. Execute default operation: the system default value is reserved for the signal processing. The default operation for most signals is to terminate the process
3List of signals supported by Linux
11. Signal transmission and capture
The kill() and raise() kill functions, like the well known kill system commands, can send signals to processes or process groups
alarm() and pause()
The kill – l command is used to view the list of signals supported by the system
The raise function allows a process to send a signal to itself
alarm(), also known as the alarm function, can set a timer in the process. When the timer specified time expires, the kernel sends the SIGALRM signal to the process.
The pause() function is used to suspend the calling process until a signal is received.
kill function:
code:
/************************************************************************************************************************************************************************************************************************ *File name: *Author: She001 *Time: *edition: *Function: test the kill function ****************************************************************************************************************************************************************************************************************************/ #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #include<stdbool.h> #include<time.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<errno.h> #include<sys/wait.h> #include<a.out.h> #include<signal.h> #include<stdarg.h> #include<sys/socket.h> #include<utime.h> #include<sys/utsname.h> #include<sys/times.h> #include<sys/un.h> #include<ctype.h> #include<dirent.h> #include<sys/time.h> #include<sys/resource.h> #include<syslog.h> #include<pthread.h> #include<signal.h> int main(int argc,char *argv[]) { printf("%s start \n",__func__); //kill(getpid(),SIGKILL); //kill(getppid(),SIGKILL); // Ctrl+d Close the terminal kill(getpid(),SIGTSTP); printf("%s end\n",__func__); return 0; }
raise function
alarm function
code:
/************************************************************************************************************************************************************************************************************************ *File name: *Author: She001 *Time: *edition: *Functions: other functions of signal ****************************************************************************************************************************************************************************************************************************/ #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #include<stdbool.h> #include<time.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<errno.h> #include<sys/wait.h> #include<a.out.h> #include<signal.h> #include<stdarg.h> #include<sys/socket.h> #include<utime.h> #include<sys/utsname.h> #include<sys/times.h> #include<sys/un.h> #include<ctype.h> #include<dirent.h> #include<sys/time.h> #include<sys/resource.h> #include<syslog.h> #include<pthread.h> #include<signal.h> //1.raise can only send signals to itself //2. After the alarm is called, the kernel sends an alarm signal to the process at the specified time (the operation of the alarm signal is to terminate the task) //3.abort//The core dumped functions //4.pause lets the task calling this function stop until the kernel sends a signal to this task int main(int argc,char *argv[]) { printf("%s start\n",__func__); //raise(SIGKILL);// kill //raise(SIGTSTP);// suspend //raise(SIGINT);// termination alarm(5); //In seconds for(int i=1;i<=10;i++) { printf("this is alarm sig!\n"); sleep(1); if(i==2) { //abort(); pause(); } } printf("%s end\n",__FILE__);//File name return 0; }
12. Signal processing
A specific signal is a process associated with a corresponding event. You can set the corresponding mode for the signal
There are two main methods of signal processing: using simple signal() function
When signal() uses the signal function to process, it is necessary to specify the signal to be processed and the processing function. It is simple to use and easy to understand
code:
/************************************************************************************************************************************************************************************************************************ *File name: *Author: She001 *Time: *edition: *Function: use of signal function ****************************************************************************************************************************************************************************************************************************/ #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #include<stdbool.h> #include<time.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<errno.h> #include<sys/wait.h> #include<a.out.h> #include<signal.h> #include<stdarg.h> #include<sys/socket.h> #include<utime.h> #include<sys/utsname.h> #include<sys/times.h> #include<sys/un.h> #include<ctype.h> #include<dirent.h> #include<sys/time.h> #include<sys/resource.h> #include<syslog.h> #include<pthread.h> #include<signal.h> //1.signal //2. Task A sends signals to Task B. Task B has three responses 1. Ignore 2. Capture 3. Default // // void sigfun(int signo) { if(signo ==SIGINT ) { printf("file is ctrl + c\n"); } else if(signo == SIGQUIT) { printf("file is ctrl + \\ \n"); } else if(signo ==SIGTSTP) { printf("file is ctrl + z \n"); } else if(signo=SIGALRM) { printf("alarm signal is buhuo1\n"); } } int main(int argc,char *argv[]) { printf("this is signal test start\n"); signal(SIGINT,sigfun); signal(SIGQUIT,sigfun); signal(SIGTSTP,sigfun); signal(SIGALRM,sigfun); int num =20; alarm(5); //Restore the original function signal of the signal(SIGINT, SIG_DFL) //Ignore the signal function singal (SIGNANT, SIG_IGN); //It can capture the termination signal of the alarm function; while(num--) { printf("test num =%d\n",num); sleep(1); } printf("this is singal end \n"); return 0; }