【Linux系统编程】进程同步与互斥:POSIX有名信号量
在 POSIX 標(biāo)準(zhǔn)中,信號量分兩種,一種是無名信號量,一種是有名信號量。無名信號量一般用于線程間同步或互斥,而有名信號量一般用于進程間同步或互斥。它們的區(qū)別和管道及命名管道的區(qū)別類似,無名信號量則直接保存在內(nèi)存中,而有名信號量要求創(chuàng)建一個文件。前面我們學(xué)習(xí)了無名信號量的使用(詳情請看《無名信號量》),這里我們學(xué)習(xí)有名信號量的使用。
1)創(chuàng)建一個有名信號量
所需頭文件:
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
當(dāng)有名信號量存在時使用:
sem_t *sem_open(const char *name, int oflag);
當(dāng)有名信號量不存在時使用:
sem_t *sem_open(const char *name, int oflag,?mode_t mode, unsigned int value);
功能:
創(chuàng)建一個有名信號量。
參數(shù):
name:信號量文件名。注意,不能指定路徑名。因為有名信號量,默認放在/dev/shm?里,如下圖:
flags:sem_open() 函數(shù)的行為標(biāo)志。
mode:文件權(quán)限(可讀、可寫、可執(zhí)行)的設(shè)置。
value:信號量初始值。
返回值:
成功:信號量的地址
失敗:SEM_FAILED
2)關(guān)閉有名信號量
所需頭文件:
#include <semaphore.h>
int sem_close(sem_t *sem);
功能:
關(guān)閉有名信號量。
參數(shù):
sem:指向信號量的指針。
返回值:
成功:0
失敗:-1
3)刪除有名信號量文件
所需頭文件:
#include <semaphore.h>
int sem_unlink(const char *name);
功能:
刪除有名信號量的文件。
參數(shù):
name:有名信號量文件名。
返回值:
成功:0
失敗:-1
4)信號量 PV 操作
用法和《POSIX 無名信號量》一樣,詳情請點此鏈接。
有名信號量實現(xiàn)進程間互斥功能:
#include<stdio.h> #include<semaphore.h> #include<fcntl.h> #include<unistd.h> #include<sys/stat.h> #include<sys/types.h>void printer(sem_t *sem, char *str) {sem_wait(sem); //信號量減一while(*str!='\0'){putchar(*str); fflush(stdout);str++;sleep(1);}printf("\n"); sem_post(sem); //信號量加一 }int main(int argc, char *argv[]) {pid_t pid;sem_t *sem = NULL;pid = fork(); //創(chuàng)建進程if(pid<0){ //出錯perror("fork error");}else if(pid == 0){ //子進程//跟open()打開方式很相似,不同進程只要名字一樣,那么打開的就是同一個有名信號量sem = sem_open("name_sem", O_CREAT|O_RDWR, 0666, 1); //信號量值為 1if(sem == SEM_FAILED){ //有名信號量創(chuàng)建失敗perror("sem_open");return -1;}char *str1 = "hello";printer(sem, str1); //打印sem_close(sem); //關(guān)閉有名信號量_exit(1);}else if(pid > 0){ //父進程//跟open()打開方式很相似,不同進程只要名字一樣,那么打開的就是同一個有名信號量sem = sem_open("name_sem", O_CREAT|O_RDWR, 0666, 1); //信號量值為 1if(sem == SEM_FAILED){//有名信號量創(chuàng)建失敗perror("sem_open");return -1;}char *str2 = "world";printer(sem, str2); //打印sem_close(sem); //關(guān)閉有名信號量wait(pid, NULL); //等待子進程結(jié)束}sem_unlink("name_sem");//刪除有名信號量return 0; }
運行結(jié)果如下:
有名信號量實現(xiàn)進程間同步功能(print2 先打印,再到 print1 打印):
print1.c 代碼如下:
#include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For mode constants */ #include <semaphore.h> #include <stdio.h>void print(sem_t *print1, sem_t *print2) {int i = 0;while(1){sem_wait(print1);i++;printf("int print1 i = %d\n", i);sem_post(print2);} }int main(int argc, char **argv) { sem_t *print1, *print2;print1 = sem_open("sem_print1", O_CREAT, 0777, 0); if(SEM_FAILED == print1){perror("sem_open");}print2 = sem_open("sem_print2", O_CREAT, 0777, 1); if(SEM_FAILED == print2){perror("sem_open");}print(print1, print2);return 0; }
print2.c 代碼如下:
#include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For mode constants */ #include <semaphore.h> #include <stdio.h>void print(sem_t *print1, sem_t *print2) {int i = 0;while(1){sem_wait(print2);i++;printf("in print2 i = %d\n", i);sleep(1);sem_post(print1);} }int main(int argc, char **argv) { sem_t *print1, *print2;print1 = sem_open("sem_print1", O_CREAT, 0777, 0); if(SEM_FAILED == print1){perror("sem_open");}print2 = sem_open("sem_print2", O_CREAT, 0777, 1); if(SEM_FAILED == print2){perror("sem_open");}print(print1, print2);return 0; }
刪除有名信號量示例代碼如下:
#include <semaphore.h> #include <stdio.h>void sem_del(char *name) {int ret;ret = sem_unlink(name);if(ret < 0){perror("sem_unlink");} }int main(int argc, char **argv) {sem_del("sem_print1"); //刪除信號量文件sem_print1sem_del("sem_print2"); //刪除信號量文件sem_print2return 0; }
makefile 代碼如下:
all:gcc sem_del.c -o sem_del -lpthreadgcc print1.c -o print1 -lpthreadgcc print2.c -o print2 -lpthread clean:rm sem_del print1 print2
運行程序時,先把有名信號量刪除(sem_del),再分別運行 print1 和 print2:
總結(jié)
以上是生活随笔為你收集整理的【Linux系统编程】进程同步与互斥:POSIX有名信号量的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Linux系统编程】线程同步与互斥:P
- 下一篇: 【Linux系统编程】进程同步与互斥:S