有名信号量在无相关进程间的同步
有名信号量的特点是把信号量的值保存在文件中。这决定了它的用途非常广:既可以用于线程,也可以用于相关进程间,甚至是不相关进程。由于有名信号量的值是保存在文件中的,所以对于相关进程来说,子进程是继承了父进程的文件描述符,那么子进程所继承的文件描述符所指向的文件是和父进程一样的,当然文件里面保存的有名信号量值就共享了。
有名信号量是位于共享内存区的,那么它要保护的资源也必须是位于共享内存区,只有这样才能被无相关的进程所共享。在下面这个例子中,服务进程和客户进程都使用shmget和shmat来获取得一块共享内存资源。然后利用有名信号量来对这块共享内存资源进行互斥保护。
server.c
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- #include <stdio.h>
- #include <semaphore.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
-
- #define SHMSZ 27
- char SEM_NAME[]= "vik";
-
- int main()
- {
- char ch;
- int shmid;
- key_t key;
- char *shm,*s;
- sem_t *mutex;
-
- //name the shared memory segment
- key = 1000;
-
- //create & initialize semaphore
- mutex = sem_open(SEM_NAME,O_CREAT,0644,1);
- if(mutex == SEM_FAILED)
- {
- perror("unable to create semaphore");
- sem_unlink(SEM_NAME);
- exit(-1);
- }
-
- //create the shared memory segment with this key
- shmid = shmget(key,SHMSZ,IPC_CREAT|0666);
- if(shmid<0)
- {
- perror("failure in shmget");
- exit(-1);
- }
-
- //attach this segment to virtual memory
- shm = shmat(shmid,NULL,0);
-
- //start writing into memory
- s = shm;
- for(ch='A';ch<='Z';ch++)
- {
- sem_wait(mutex);
- *s++ = ch;
- sem_post(mutex);
- }
-
- //the below loop could be replaced by binary semaphore
- while(*shm != '*')
- {
- sleep(1);
- }
- sem_close(mutex);
- sem_unlink(SEM_NAME);
- shmctl(shmid, IPC_RMID, 0);
- exit(0);
- }
-
client.c
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- #include <stdio.h>
- #include <semaphore.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
-
- #define SHMSZ 27
- char SEM_NAME[]= "vik";
-
- int main()
- {
- char ch;
- int shmid;
- key_t key;
- char *shm,*s;
- sem_t *mutex;
-
- //name the shared memory segment
- key = 1000;
-
- //create & initialize existing semaphore
- mutex = sem_open(SEM_NAME,0,0644,0);
- if(mutex == SEM_FAILED)
- {
- perror("reader:unable to execute semaphore");
- sem_close(mutex);
- exit(-1);
- }
-
- //create the shared memory segment with this key
- shmid = shmget(key,SHMSZ,0666);
- if(shmid<0)
- {
- perror("reader:failure in shmget");
- exit(-1);
- }
-
- //attach this segment to virtual memory
- shm = shmat(shmid,NULL,0);
-
- //start reading
- s = shm;
- for(s=shm;*s!=NULL;s++)
- {
- sem_wait(mutex);
- putchar(*s);
- sem_post(mutex);
- }
-
- //once done signal exiting of reader:This can be replaced by another semaphore
- *shm = '*';
- sem_close(mutex);
- shmctl(shmid, IPC_RMID, 0);
- exit(0);
- }
|