Linux系统编程 |
您所在的位置:网站首页 › 多线程的同步和互斥的区别在哪 › Linux系统编程 |
在 POSIX 标准中,信号量分两种,一种是无名信号量,一种是有名信号量。无名信号量一般用于线程间同步或互斥,而有名信号量一般用于进程间同步或互斥。它们的区别和管道及命名管道的区别类似,无名信号量则直接保存在内存中,而有名信号量要求创建一个文件。前面我们学习了无名信号量的使用(详情请看《无名信号量》),这里我们学习有名信号量的使用。
1)创建一个有名信号量 所需头文件: #include #include #include
当有名信号量存在时使用: sem_t *sem_open(const char *name, int oflag); 当有名信号量不存在时使用: sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value); 功能: 创建一个有名信号量。 参数: name:信号量文件名。注意,不能指定路径名。因为有名信号量,默认放在/dev/shm 里,如下图: flags:sem_open() 函数的行为标志。 mode:文件权限(可读、可写、可执行)的设置。 value:信号量初始值。 返回值: 成功:信号量的地址 失败:SEM_FAILED
2)关闭有名信号量 所需头文件: #include int sem_close(sem_t *sem); 功能: 关闭有名信号量。 参数: sem:指向信号量的指针。 返回值: 成功:0 失败:-1
3)删除有名信号量文件 所需头文件: #include int sem_unlink(const char *name); 功能: 删除有名信号量的文件。 参数: name:有名信号量文件名。 返回值: 成功:0 失败:-1
4)信号量 PV 操作 用法和《POSIX 无名信号量》一样,详情请点此链接。
有名信号量实现进程间互斥功能: #include #include #include #include #include #include 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(); //创建进程 if(pid 0){ //父进程 //跟open()打开方式很相似,不同进程只要名字一样,那么打开的就是同一个有名信号量 sem = sem_open("name_sem", O_CREAT|O_RDWR, 0666, 1); //信号量值为 1 if(sem == SEM_FAILED){//有名信号量创建失败 perror("sem_open"); return -1; } char *str2 = "world"; printer(sem, str2); //打印 sem_close(sem); //关闭有名信号量 wait(pid, NULL); //等待子进程结束 } sem_unlink("name_sem");//删除有名信号量 return 0; }运行结果如下:
有名信号量实现进程间同步功能(print2 先打印,再到 print1 打印): print1.c 代码如下: #include /* For O_* constants */ #include /* For mode constants */ #include #include 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 /* For O_* constants */ #include /* For mode constants */ #include #include 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 #include 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_print1 sem_del("sem_print2"); //删除信号量文件sem_print2 return 0; } makefile 代码如下: all: gcc sem_del.c -o sem_del -lpthread gcc print1.c -o print1 -lpthread gcc print2.c -o print2 -lpthread clean: rm sem_del print1 print2 运行程序时,先把有名信号量删除(sem_del),再分别运行 print1 和 print2:
本教程示例代码下载请点此处。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |