Linux信号灯

概念:是不同进程间或一个给定进程内部不同线程间同步的机制。类似我们的

PV操作概念:

生产者和消费者场景

P(S) 含义如下:

     if  (信号量的值大于0) { 

             申请资源的任务继续运行;

             信号量的值减一;

    } else {  

            申请资源的任务阻塞;

    }

V(S) 含义如下:

     信号量的值加一;

     if (有任务在等待资源) {  

            唤醒等待的任务,让其继续运行

    }

信号灯P操作

int sem_wait(sem_t *sem);

获取资源,如果信号量为0,表示这时没有相应资源空闲,那么调用线程就将挂起,直到有空闲资源可以获取

信号灯V操作

int sem_post(sem_t *sem);

释放资源,如果没有线程阻塞在该sem上,表示没有线程等待该资源,这时该函数就对信号量的值进行增1操作,表示同类资源多增加了一个。如果至少有一个线程阻塞在该sem上,表示有线程等待资源,信号量为0,这时该函数保持信号量为0不变,并使某个阻塞在该sem上的线程从sem_wait函数中返回

注意:编译posix信号灯需要加pthread动态库。

三种信号灯:

Posix 有名信号灯

Posix 无名信号灯 (linux只支持线程同步)

System V 信号灯

Posix 有名信号灯和无名信号灯使用:

 有名信号灯打开:

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:name是给信号灯起的名字
oflag:打开方式,常用O_CREAT 
mode:文件权限。常用0666
value:信号量值。二元信号灯值为1,普通表示资源数目

信号灯文件位置:/dev/shm

有名信号灯关闭

int sem_close(sem_t *sem);

有名信号灯的删除

int sem_unlink(const char* name);

 有名信号灯:

 sem_w.c

#include<stdio.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<semaphore.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>


int main()
{
	key_t key;
	key = ftok(".",100);
	if(key < 0)
	{
		perror("ftok");
		return 0;
	}
	int shmid;
	shmid = shmget(key,500,0666|IPC_CREAT);
	if(shmid < 0)
	{
		perror("shmget");
		return 0;
	}

	char* shmaddr;
	shmaddr = shmat(shmid,NULL,0);

	sem_t* sem_r,*sem_w;
	sem_r = sem_open("mysem_r",O_CREAT|O_RDWR,0666,0);
	sem_w = sem_open("mysem_w",O_CREAT|O_RDWR,0666,1);

	while(1)
	{
		sem_wait(sem_w);
		printf(">");
		fgets(shmaddr,500,stdin);
		sem_post(sem_r);
	}

	return 0;
}

sem_r.c

#include<stdio.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<semaphore.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>


int main()
{
	key_t key;
	key = ftok(".",100);
	if(key < 0)
	{
		perror("ftok");
		return 0;
	}
	int shmid;
	shmid = shmget(key,500,0666|IPC_CREAT);
	if(shmid < 0)
	{
		perror("shmget");
		return 0;
	}

	char* shmaddr;
	shmaddr = shmat(shmid,NULL,0);

	sem_t* sem_r,*sem_w;
	sem_r = sem_open("mysem_r",O_CREAT|O_RDWR,0666,0);
	sem_w = sem_open("mysem_w",O_CREAT|O_RDWR,0666,1);

	while(1)
	{
		sem_wait(sem_r);
		printf("%s\n",shmaddr);
		sem_post(sem_w);
	}

	return 0;
}

运行结果: 

test_r.c

#include<stdio.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<semaphore.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<signal.h>

void handle(int sig)
{
    sem_unlink("mysem_w");
	exit(0);
}


int main()
{
	struct sigaction act;
	act.sa_handler = handle;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);
	sigaction(SIGINT,&act,NULL);

	key_t key;
	key = ftok(".",100);
	if(key < 0)
	{
		perror("ftok");
		return 0;
	}
	int shmid;
	shmid = shmget(key,500,0666|IPC_CREAT);
	if(shmid < 0)
	{
		perror("shmget");
		return 0;
	}

	char* shmaddr;
	shmaddr = shmat(shmid,NULL,0);

	sem_t* sem_r,*sem_w;
	sem_r = sem_open("mysem_r",O_CREAT|O_RDWR,0666,0);
	sem_w = sem_open("mysem_w",O_CREAT|O_RDWR,0666,1);

	while(1)
	{
		sem_wait(sem_r);
		printf("%s\n",shmaddr);
		sem_post(sem_w);
	}

	return 0;
}

 test_w.c

#include<stdio.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<semaphore.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<signal.h>

void handle(int sig)
{
	sem_unlink("mysem_r");
	exit(0);
}

int main()
{
	struct sigaction act;
	act.sa_handler = handle;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);
	sigaction(SIGINT,&act,NULL);

	key_t key;
	key = ftok(".",100);
	if(key < 0)
	{
		perror("ftok");
		return 0;
	}
	int shmid;
	shmid = shmget(key,500,0666|IPC_CREAT);
	if(shmid < 0)
	{
		perror("shmget");
		return 0;
	}

	char* shmaddr;
	shmaddr = shmat(shmid,NULL,0);

	sem_t* sem_r,*sem_w;
	sem_r = sem_open("mysem_r",O_CREAT|O_RDWR,0666,0);
	sem_w = sem_open("mysem_w",O_CREAT|O_RDWR,0666,1);

	while(1)
	{
		sem_wait(sem_w);
		printf(">");
		fgets(shmaddr,500,stdin);
		sem_post(sem_r);
	}

	return 0;
}

运行结果: 

无名信号灯初始化 

int sem_init(sem_t *sem, int shared, unsigned int value);
参数:
sem:需要初始化的信号灯变量
shared: shared指定为0,表示信号量只能由初始化这个信号量的进程使用,不能在进程间使用,linux 不支持进程间同步。
Value:信号量的值

 无名信号灯销毁

int sem_destroy(sem_t* sem);

无名信号灯: 

        该程序包含一个主进程和一个读取进程。主进程负责从标准输入中读取用户输入,并将其写入共享内存中,读取进程则从共享内存中读取数据并输出到标准输出。

1.信号处理函数,用于在程序中断时销毁信号量destroysem

2.读取进程函数readmem

sem_wait(&sem_r); // 等待写入信号量

printf("%s\n",shmaddr); // 读取共享内存内容并打印

sem_post(&sem_w); // 发送写入信号量

3.设置信号处理函数sigaction

4.生成共享内存ftok

5.创建共享内存shmget

6.将共享内存连接到当前进程的地址空间shmat

7.初始化信号量sem_init

8.创建读取进程pthread_create

9.读取数据并输出到标准输出

 sem_wait(&sem_w); // 等待读取信号量
 printf(">"); 
 fgets(shmaddr,500,stdin); // 从标准输入读取数据到共享内存
 sem_post(&sem_r); // 发送读取信号量

具体代码: 

#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <semaphore.h>

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>
#include <pthread.h>


sem_t sem_r,sem_w;
char *shmaddr;
void destroysem(int sig){

	sem_destroy(&sem_r);
	sem_destroy(&sem_w);
	exit(0);

}

void *readmem(void *arg){
	while(1){
		sem_wait(&sem_r);
		printf("%s\n",shmaddr);
		sem_post(&sem_w);

	}

}


int main(){


	key_t key;
	int shmid;

	struct sigaction act;
	act.sa_handler = destroysem;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);

	sigaction(SIGINT,&act,NULL);

	key = ftok(".",100);
	if(key<0){
		perror("ftok");
		return 0;
	}

	shmid = shmget(key,500,0666|IPC_CREAT);
	if(shmid<0){
		perror("shmget");
		return 0;
	}

	shmaddr = shmat(shmid,NULL,0);


	sem_init(&sem_r,0,0);
	sem_init(&sem_w,0,1);

	pthread_t tid;
	pthread_create(&tid,NULL,readmem,NULL);

	while(1){
		sem_wait(&sem_w);
		printf(">");
		fgets(shmaddr,500,stdin);
		sem_post(&sem_r);
	}

}

        这个程序的主要功能是从标准输入中读取用户输入,并将其写入共享内存,然后另一个进程从共享内存中读取数据并打印到标准输出。

运行结果: 

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-15 15:52:04       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-15 15:52:04       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-15 15:52:04       87 阅读
  4. Python语言-面向对象

    2024-03-15 15:52:04       96 阅读

热门阅读

  1. 安装vm tool

    2024-03-15 15:52:04       43 阅读
  2. 《Effective Modern C++》- 极精简版 36-42条

    2024-03-15 15:52:04       40 阅读
  3. 记录启动Dubbo-admin遇到的问题

    2024-03-15 15:52:04       57 阅读
  4. 软考高级:软件工程集成测试的策略概念和例题

    2024-03-15 15:52:04       48 阅读
  5. Uniapp Vue2 image src动态绑定static目录下的图片

    2024-03-15 15:52:04       44 阅读
  6. 力扣题库第9题:找到字符串中所有的异位词

    2024-03-15 15:52:04       44 阅读
  7. Web安全攻防措施

    2024-03-15 15:52:04       39 阅读
  8. 程序分享--排序算法--冒泡排序

    2024-03-15 15:52:04       41 阅读