Multi-thread synchronization mechanism

1, spinlock

For a short wait, do not deserve the kind of short sleep.

  jmp 11b
12:
get_lock:
    lock bts $0, 0x6000
    jc get_lock
  lock incw smp_cpus
  mov $smp_cpus, %bx
  lock btr $0, 0x6000    /*release lock*/
  mov 0(%bx), %si

  ...

smp_ap_boot_code_end:

This is the start of each nuclear obtain its own nuclear numbered according smp_cpus, so as to position different "points" on the screen, then loop increments its ascii code.

 

2, atomic_t

This is the number of atoms linux kernel, there is a corresponding atomic_inc / dec () series method.

On x86, implementations rely on its internal lock instruction prefix.

 

3,semaphore

sem_init (); sem_wait (); sem_post (); sem_destroy ();

If want to fork () is still used, need to use shared memory area.

Also after each post, only to wake up in a queue process. Because the queue of processes waiting for sure because sem_wait () to enter, they naturally will call sem_post () is called the "next."

A particularly good on SO:

https://stackoverflow.com/questions/16400820/how-to-use-posix-semaphores-on-forked-processes-in-c

 

How to use POSIX semaphores on forked processes in C?

I want to fork multiple processes and then use a semaphore on them. Here is what I tried:

sem_init(&sem, 1, 1); /* semaphore*, pshared, value */ . . . if(pid != 0){ /* parent process */ wait(NULL); /* wait all child processes */ printf("\nParent: All children have exited.\n"); . . /* cleanup semaphores */ sem_destroy(&sem); exit(0); } else{ /* child process */ sem_wait(&sem); /* P operation */ printf(" Child(%d) is in critical section.\n",i); sleep(1); *p += i%3; /* increment *p by 0, 1 or 2 based on i */ printf(" Child(%d) new value of *p=%d.\n",i,*p); sem_post(&sem); /* V operation */ exit(0); }
.....

 
A high praise answer:

The problem you are facing is the misunderstanding of sem_init() function. When you read the manual page you will see this:

The pshared argument indicates whether this semaphore is to be shared between the threads of a process, or between processes.

If you are done reading up to this point, you will think that the non-zero value of pshared will make the semaphore inter-process semaphore. However, this is wrong. You should continue reading and you'll understand that you have to locate the semaphore in a shared memory region. To do that, several functions can be used as you can see below:

If pshared is nonzero, then the semaphore is shared between processes, and should be located in a region of shared memory (see shm_open(3), mmap(2), and shmget(2)). (Since a child created by fork(2) inherits its parent's memory mappings, it can also access the semaphore.) Any process that can access the shared memory region can operate on the semaphore using sem_post(3), sem_wait(3), etc.

I find this approach as a more complicated approach than others, therefore I want to encourage people to use sem_open() instead of sem_init().

Below you can see a complete program illustrates the following:

  • How to allocate shared memory and use shared variables between forked processes.
  • How to initialize a semaphore in a shared memory region and is used by multiple processes.
  • How to fork multiple processes and make the parent wait until all of its children exit.
#include <stdio.h>          /* printf() */ #include <stdlib.h> /* exit(), malloc(), free() */ #include <sys/types.h> /* key_t, sem_t, pid_t */ #include <sys/shm.h> /* shmat(), IPC_RMID */ #include <errno.h> /* errno, ECHILD */ #include <semaphore.h> /* sem_open(), sem_destroy(), sem_wait().. */ #include <fcntl.h> /* O_CREAT, O_EXEC */ int main (int argc, char **argv){ int i; /* loop variables */ key_t shmkey; /* shared memory key */ int shmid; /* shared memory id */ sem_t *sem; /* synch semaphore *//*shared */ pid_t pid; /* fork pid */ int *p; /* shared variable *//*shared */ unsigned int n; /* fork count */ unsigned int value; /* semaphore value */ /* initialize a shared variable in shared memory */ shmkey = ftok ("/dev/null", 5); /* valid directory name and a number */ printf ("shmkey for p = %d\n", shmkey); shmid = shmget (shmkey, sizeof (int), 0644 | IPC_CREAT); if (shmid < 0){ /* shared memory error check */ perror ("shmget\n"); exit (1); } p = (int *) shmat (shmid, NULL, 0); /* attach p to shared memory */ *p = 0; printf ("p=%d is allocated in shared memory.\n\n", *p); /********************************************************/ printf ("How many children do you want to fork?\n"); printf ("Fork count: "); scanf ("%u", &n); printf ("What do you want the semaphore value to be?\n"); printf ("Semaphore value: "); scanf ("%u", &value); /* initialize semaphores for shared processes */ sem = sem_open ("pSem", O_CREAT | O_EXCL, 0644, value); /* name of semaphore is "pSem", semaphore is reached using this name */ printf ("semaphores initialized.\n\n"); /* fork child processes */ for (i = 0; i < n; i++){ pid = fork (); if (pid < 0) { /* check for error */ sem_unlink ("pSem"); sem_close(sem); /* unlink prevents the semaphore existing forever */ /* if a crash occurs during the execution */ printf ("Fork error.\n");  } else if (pid == 0) break; /* child processes */ } /******************************************************/ /****************** PARENT PROCESS ****************/ /******************************************************/ if (pid != 0){ /* wait for all children to exit */ while (pid = waitpid (-1, NULL, 0)){ if (errno == ECHILD) break; } printf ("\nParent: All children have exited.\n"); /* shared memory detach */ shmdt (p); shmctl (shmid, IPC_RMID, 0); /* cleanup semaphores */ sem_unlink ("pSem"); sem_close(sem); /* unlink prevents the semaphore existing forever */ /* if a crash occurs during the execution */ exit (0); } /******************************************************/ /****************** CHILD PROCESS *****************/ /******************************************************/ else{ sem_wait (sem); /* P operation */ printf (" Child(%d) is in critical section.\n", i); sleep (1); *p += i % 3; /* increment *p by 0, 1 or 2 based on i */ printf (" Child(%d) new value of *p=%d.\n", i, *p); sem_post (sem); /* V operation */ exit (0); } }
 

Also concerned about the sem_open () function.

Guess you like

Origin www.cnblogs.com/xiang-yin/p/12114209.html