美文网首页
Linux系统编程6:信号量

Linux系统编程6:信号量

作者: jdzhangxin | 来源:发表于2018-04-30 09:10 被阅读77次

0. 信号量

  • 背景
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc,char * argv[]){
 
    fork();
    int i=0;
    for(;i<5;i++){
        printf("PID:%d,enter\n",getpid());
        sleep(1);// do something
        printf("PID:%d,do something\n",getpid());
        printf("PID:%d,leave\n",getpid());
    }
}

数据竞争

  • 来源


  • 分类

根据共享资源的数目可分为二值信号量和计数信号量两类。

No. 分类 取值 e.g.
1 二值信号量 01 指示锁
2 计数信号量 0n 停车场电子牌
指示锁 停车场电子指示牌 信号量
  • 作用
    控制多进程共享资源的访问(资源有限并且不共享)

  • 信号

No. 分类 取值
1 P(信号量) 0:挂起进程;>0:减1
2 V(信号量) 0:恢复进程;>0:加1
  • 本质
    任一时刻只能有一个进程访问临界区(代码),数据更新的代码。

1. POSIX 信号量

  • 资料:unpv22e-ch10.1~10.13
  • 查看:man sem_overview

1.1 接口

  • 头文件:semaphore.h

  • 库:pthread

  • 分类
    信号量分为命名信号量(基于文件)与匿名信号量(基于内存)两种。

1.2 函数

1.2.1 命名信号量/基于文件

No. 操作 函数
1 创建 sem_t *sem_open(const char *name, int oflag, mode_t mode,unsigned int value)
2 删除 int sem_unlink(const char *name)
3 打开 sem_t *sem_open(const char *name, int oflag)
4 关闭 int sem_close(sem_t *sem)
5 挂出 int sem_post(sem_t *sem)
6 等待 int sem_wait(sem_t *sem)
7 尝试等待 int sem_trywait(sem_t *sem)
8 获取信号量的值 int sem_getvalue(sem_t *sem, int *sval)
1.2.1.1 创建
sem_t *sem_open(const char *name, int oflag, mode_t mode,unsigned int value)
  • 参数
No. 参数 含义
1 name 信号量IPC名字
2 oflag 标志
3 mode 权限位
4 value 信号量初始值

IPC名字有什么要求?

  • 返回值
No. 返回值 含义
1 SEM_FAILED 信号量的指针
2 SEM_FAILED 出错
  • 示例
1.2.1.2 删除
int sem_unlink(const char *name)
  • 参数
No. 参数 含义
1 name 信号量IPC名字
  • 返回值
No. 返回值 含义
1 -1 出错
2 0 成功
1.2.1.3 打开
sem_t *sem_open(const char *name, int oflag)
  • 参数
No. 参数 含义
1 name 信号量IPC名字
2 oflag 标志
  • 返回值
No. 返回值 含义
1 SEM_FAILED 信号量的指针
2 SEM_FAILED 出错
1.2.1.4 关闭
int sem_close(sem_t *sem)
  • 参数
No. 参数 含义
1 sem 信号量的指针
  • 返回值
No. 返回值 含义
1 -1 出错
2 0 成功
1.2.1.5 挂出
int sem_post(sem_t *sem)
  • 参数
No. 参数 含义
1 sem 信号量的指针
  • 返回值
No. 返回值 含义
1 -1 出错
2 0 成功
1.2.1.6 等待
int sem_wait(sem_t *sem)
  • 参数
No. 参数 含义
1 sem 信号量的指针
  • 返回值
No. 返回值 含义
1 -1 出错
2 0 成功
1.2.1.7 尝试等待
int sem_trywait(sem_t *sem)
  • 参数
No. 参数 含义
1 sem 信号量的指针
  • 返回值
No. 返回值 含义
1 -1 出错
2 0 成功
1.2.1.8 获取信号量的值
int sem_getvalue(sem_t *sem, int *sval)
  • 参数
No. 参数 含义
1 sem 信号量的指针
2 sval 信号量的值
  • 返回值
No. 返回值 含义
1 -1 出错
2 0 成功
数据竞争解决方法

上面竞争可以使用信号量解决。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <semaphore.h>
 
int main(int argc,char * argv[]){
 
    sem_t* sem = sem_open("/sem.tmp",O_CREAT|O_RDWR,0644,1);
    fork();
    int i=0;
    for(;i<5;i++){
        sleep(1);
        sem_wait(sem);
        printf("PID:%d,enter\n",getpid());
        printf("PID:%d,do something\n",getpid());
        printf("PID:%d,leave\n",getpid());
        sem_post(sem);
    }
}

1.2.2 匿名信号量/基于内存

No. 操作 函数
1 初始化 int sem_init (sem_t *sem , int pshared, unsigned int value)
2 销毁 int sem_destroy(sem_t *sem)
3 挂出 int sem_post(sem_t *sem)
4 等待 int sem_wait(sem_t *sem)
5 尝试等待 int sem_trywait(sem_t *sem)
6 获取信号量的值 int sem_getvalue(sem_t *sem, int *sval)

其中3~4操作与命名信号量相同。

1.2.2.1 初始化
int sem_init (sem_t *sem , int pshared, unsigned int value)
  • 参数
No. 参数 含义
1 sem 信号量的指针
2 pshared 共享方式。0:线程间共享;1:进程间共享,需要共享内存
3 value 信号量初始值
  • 返回值
No. 返回值 含义
1 -1 出错
2 0 成功
1.2.2.2 销毁
int sem_destroy(sem_t *sem)
  • 参数
No. 参数 含义
1 sem 信号量的指针
  • 返回值
No. 返回值 含义
1 -1 出错
2 0 成功
数据竞争解决方法
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <semaphore.h>
 
int main(int argc,char * argv[]){
 
    sem_t* sem = sem_open("/sem.tmp",O_CREAT|O_RDWR,0644,0);
    fork();
    int i=0;
    for(;i<5;i++){
        sleep(1);
        sem_wait(sem);
        printf("PID:%d,enter\n",getpid());
        printf("PID:%d,do something\n",getpid());
        printf("PID:%d,leave\n",getpid());
        sem_post(sem);
    }
}

小结

命名信号量与匿名信号量

案例

模拟一个停车场的电子显示牌

  • park.cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <semaphore.h>
 
int main(int argc,char * argv[]){
    sem_t* sem = sem_open(argv[1],O_CREAT,0644,atoi(argv[2]));
}
  • car.cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <semaphore.h>
 
void handler(int sig){
    printf("PID:%d,prepare to leave\n",getpid());
}
 
int main(int argc,char * argv[]){
    signal(SIGINT,handler);
    sem_t* sem = sem_open(argv[1],O_RDWR);
    sem_wait(sem);
    int val;
    sem_getvalue(sem,&val);
    printf("PID:%d,enter. park %d\n",getpid(),val);
    printf("PID:%d,do something\n",getpid());
    pause();
    sem_post(sem);
    sem_getvalue(sem,&val);
    printf("PID:%d,leave. park %d\n",getpid(),val);
}
  • car_try.cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <semaphore.h>
 
void handler(int sig){
    printf("PID:%d,prepare to leave\n",getpid());
}
 
int main(int argc,char * argv[]){
 
    signal(SIGINT,handler);
 
    sem_t* sem = sem_open(argv[1],O_RDWR);
    if(-1 == sem_trywait(sem)){
        perror("no park");
        return 1;
    }
    int val;
    sem_getvalue(sem,&val);
    printf("PID:%d,enter. park %d\n",getpid(),val);
    printf("PID:%d,do something\n",getpid());
    pause();
    sem_post(sem);
    sem_getvalue(sem,&val);
    printf("PID:%d,leave. park %d\n",getpid(),val);
}

问题

命名信号量与匿名信号量能否用于非亲缘线程?

练习

把信号量封装成一个信号量类

相关文章

  • Linux系统编程6:信号量

    0. 信号量 背景 数据竞争 来源 分类 根据共享资源的数目可分为二值信号量和计数信号量两类。 作用控制多进程共享...

  • Linux系统编程—信号量

    大家知道,互斥锁可以用于线程间同步,但是,每次只能有一个线程抢到互斥锁,这样限制了程序的并发行。如果我们希望允许多...

  • linux系统编程环境配置

    Windows 10系统下Linux子系统如何配置系统编程环境 主要针对《Linux/Unix系统编程手册》代码 ...

  • 线程同步与互斥

    Linux--线程编程 多线程编程-互斥锁 线程同步与互斥 互斥锁 信号量 条件变量 互斥锁 互斥锁的基本使用...

  • Linux 系统编程 — 细说系统调用规范,入行要先熟悉套路

    节选自 《攻克 Linux 系统编程》 本课程主要带大家深入研究 Linux 系统编程。系统编程的任务,可以定义为...

  • 新手怎么在Linux系统上用c语言编程

    从课程目录来看,课程包含两部分:标准C语言编程和Linux系统编程。C语言编程使用C语言标准库;Linux系统编程...

  • Android binder解析

    Linux 系统提供的进程间通信(IPC)方式 Signals 信号量(System V IPC) Pipes 管...

  • Linux

    操作系统 Linux进程间通信方式:Socket、共享内存、消息队列、信号量 epoll、select、poll ...

  • python 不同环境的安装

    1.在Linux系统下搭建python编程换环境 Linux系统是为编程而设计的,因此在大多数Linux计算机中,...

  • [读书笔记]并发和竞态(第五章)

    综述 并发问题是编程中经常遇到的难题,我们需要学会针对并发产生的竞态进行编程 一、信号量和互斥体 Linux上信号...

网友评论

      本文标题:Linux系统编程6:信号量

      本文链接:https://www.haomeiwen.com/subject/jlrmhftx.html