00. 目录

文章目录

  • 00. 目录
  • 01. 概述
  • 02. 相关函数
    • 2.1 创建有名信号量
    • 2.2 关闭有名信号量
    • 2.3 删除有名信号量
    • 2.4 信号量P操作
    • 2.5 信号量V操作
  • 03. 程序示例
  • 04. 附录

01. 概述

在 POSIX 标准中,信号量分两种,一种是无名信号量,一种是有名信号量。无名信号量一般用于线程间同步或互斥,而有名信号量一般用于进程间同步或互斥。它们的区别和管道及命名管道的区别类似,无名信号量则直接保存在内存中,而有名信号量要求创建一个文件。

02. 相关函数

2.1 创建有名信号量

#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <semaphore.h>sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag,mode_t mode, unsigned int value);Link with -pthread.
功能:创建一个有名信号量。
参数:name:信号量文件名。注意,不能指定路径名。因为有名信号量,默认放在/dev/shm 里   flags:sem_open() 函数的行为标志。mode:文件权限(可读、可写、可执行)的设置。value:信号量初始值。
返回值:成功:信号量的地址失败:SEM_FAILED

2.2 关闭有名信号量

#include <semaphore.h>
int sem_close(sem_t *sem);
Link with -pthread.
功能:关闭有名信号量。
参数:sem:指向信号量的指针。
返回值:成功:0失败:-1

2.3 删除有名信号量

#include <semaphore.h>int sem_unlink(const char *name);
功能:删除有名信号量的文件。
参数:name:有名信号量文件名。
返回值:成功:0失败:-1

2.4 信号量P操作

#include <semaphore.h>int sem_wait(sem_t *sem);
功能:将信号量的值减 1。操作前,先检查信号量(sem)的值是否为 0,若信号量为 0,此函数会阻塞,直到信号量大于 0 时才进行减 1 操作。
参数:sem:信号量的地址。
返回值:成功:0失败: - 1int sem_trywait(sem_t *sem);
   以非阻塞的方式来对信号量进行减 1 操作。
   若操作前,信号量的值等于 0,则对信号量的操作失败,函数立即返回。int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
   限时尝试将信号量的值减 1
   abs_timeout:绝对时间

abs_timeout补充说明

struct timespec {time_t tv_sec;      /* seconds */ // 秒long   tv_nsec;   /* nanosecondes*/ // 纳秒
}time_t cur = time(NULL);      //获取当前时间。
struct timespec t;              //定义timespec 结构体变量t
t.tv_sec = cur + 1;               // 定时1秒
sem_timedwait(&cond, &t);

2.5 信号量V操作

#include <semaphore.h>int sem_post(sem_t *sem);
功能:将信号量的值加 1 并发出信号唤醒等待线程(sem_wait())。
参数:sem:信号量的地址。
返回值:成功:0失败:-1

03. 程序示例

示例一:有名信号量实现进程间互斥功能

#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(); //创建进程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){ //有名信号量创建失败perror("sem_open");return -1;}char *str1 = "hello";printer(sem, str1); //打印sem_close(sem); //关闭有名信号量_exit(1);}else if(pid > 0){ //父进程//跟open()打开方式很相似,不同进程只要名字一样,那么打开的就是同一个有名信号量sem = sem_open("name_sem", O_CREAT|O_RDWR, 0666, 1); //信号量值为 1if(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;
}

测试结果:

deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ ./a.out
hello
world
deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$

示例二: 有名信号量实现进程间同步功能(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;
}

04. 附录

【Linux系统编程】POSIX有名信号量相关推荐

  1. Linux系统编程:IPC信号量

    文章内容 1. 信号量 2. 函数 2.1 命名信号量 / 基于文件 2.2 匿名信号量 / 基于内存 3. 读写锁 信号量:用于解决数据竞争,如同火车道上的信号灯,用来管理共享火车道(共享内存) 1 ...

  2. 【Linux系统编程学习】匿名管道pipe与有名管道fifo

    此为牛客Linux C++和黑马Linux系统编程课程笔记. 0. 关于进程通信 Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间.任何一个进程的全局变量在另一个进程中都看不到 ...

  3. linux有名管道数据异常,Linux系统编程—有名管道

    ▋****1. 管道的概念 管道,又名「无名管理」,或「匿名管道」,管道是一种非常基本,也是使用非常频繁的IPC方式. 1.1 管道本质 管道的本质也是一种文件,不过是伪文件,实际上是一块内核缓冲区, ...

  4. Linux——POSIX有名信号量

    有名信号量 作用:主要用于同步线程或进程 头文件:#include <semaphore.h> 创建或打开信号量 /** 输入:const char* name               ...

  5. 嵌入式Linux系统编程学习之二十五信号量

    文章目录 前言 一.System V IPC 机制:信号量 1. semget 函数 2. semop 函数 3. semctl 函数 二.Posix 有名信号量 前言   信号量与信号量集的概念如下 ...

  6. 【Linux】一步一步学Linux系统编程教程汇总(暂时暂停更新......)

    00. 目录 文章目录 00. 目录 01. 概述和标准 02. 文件操作 03. 进程概念 04. 进程间通信 05. 多线程 06. 信号 07. 同步与互斥 08. 高级IO 09. 其它 10 ...

  7. Linux系统编程 复习笔记

    4 文件IO 操作 #include<fcntl.h> #include<unistd.h>#include<sys/types.h> creat int fd=c ...

  8. Linux系统编程笔记

    文章目录 1.Linux系统编程 2.文件IO 2.1 文件描述符 2.2 open 2.3 perror 2.4 close 2.5 write 2.6 read 2.7 remove 2.8 系统 ...

  9. 【北京迅为iMX6ULL】嵌入式学习之Linux系统编程视频教程

    什么是Linux系统编程? Linux系统编程也叫Linux下的高级编程,是介于应用层和驱动层之间的. 学习了哪些知识后可以学习Linux系统编程? C语言基础.Linux基本操作命令 怎么学习Lin ...

  10. 【读书笔记】linux系统编程

    linux系统编程 原作名:Linux System Programming 作者: Robert Love 第一章 入门和基本概念 1.1 系统编程 应用程序需要与更高层次的库进行交互,系统程序就是 ...

最新文章

  1. Cause:compileSdkVersion is not specified
  2. 人脸识别引擎SeetaFaceEngine简介及在windows7 vs2013下的编译
  3. 华为畅享8的悬浮窗在哪里_华为畅享8悬浮球设置 | 手游网游页游攻略大全
  4. android view的隐藏和显示_Android使用Viewpager实现3D卡片翻动效果
  5. Linux(UOS) Qt不能播放音频的问题
  6. 【转载】Linux下有趣的命令
  7. 前端学习(1876)vue之电商管理系统电商系统之整体布局
  8. log4j2到oracle,Log4j2进阶使用(更多高级特性)
  9. Turtlebot3调试必看——爬坑笔记
  10. 工作方式 柔らかいコミュニケーション
  11. 施密特:乔布斯影响力还没有完全释放
  12. Juniper Junos DoS漏洞CVE-2017-2345 10.2及相关产品和平台均受影响
  13. 全国OA系统下载地址(全)
  14. 生命计算机在线,抖音死亡计算器寿命计算器在线测试入口 使用生命年龄计算器...
  15. 小水智能-智能楼宇智慧建筑3D可视化系统,实现了数据的整合
  16. python system interpreter_2. Using the Python Interpreter:使用Python解释器
  17. C#使用BouncyCastle来实现私钥加密,公钥解密的方法
  18. 用Burg法估计AR模型的参数原理详解及matlab实现
  19. C#项目启动会闪退问题解决
  20. [翻译] 在 Overleaf 中上传项目

热门文章

  1. easy ui 使用总结
  2. GIS数据格式整理之Coverage篇
  3. POJ 3349 Snowflake Snow Snowflakes
  4. html 在tomcat中访问不到_安全服务之安全基线及加固(四)Tomcat篇
  5. C语言字符串-字符串排序
  6. Java黑皮书课后题第4章:*4.26(金融应用:货币单位)重写程序清单2-10,解决将float型值转换为int型值时可能会造成精度损失的问题。读取的输入值是一个字符串,比如“11.56“
  7. C语言学习之输入10个数,输出其中最大的一个数。
  8. 启动日志_Hybris服务器启动日志分析
  9. luogu P2512 [HAOI2008]糖果传递
  10. Dropwizard入门及开发步骤