linux——PV操作

复制代码
int semop(int semid ,struct sembuf *sops ,size_t nsops); 
//用户改变信号量的值。也就是使用资源还是释放资源使用权 
包含头文件: 
          include<sys/sem.h> 
参数: 
          semid : 信号量的标识码。也就是semget()的返回值 
          sops是一个指向结构体数组的指针。 
          struct   sembuf{ 
                           unsigned short  sem_num;//信号灯编号; 
                           short  sem_op;//对该信号量的操作。‐1 ,P操作,1 ,V操作 
                           short sem_flg;0阻塞,1非阻塞 
                         }; 
            sem_op : 操作信号灯的个数 
        //如果其值为正数,该值会加到现有的信号内含值中。通常用于释放所控资源的使用权;
        如果sem_op的值为负数,而其绝对值又大于信号的现值,操作将会阻塞,直到信号值大于
        或等于sem_op的绝对值。
        通常用于获取资源的使用权;如果sem_op的值为0,则操作将暂时阻塞,直到信号的值变为0。 

#include<stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <unistd.h>


#define SEM_READ 0
#define SEM_WRITE 1
union semnum
{
	int val;
};


void Poperation(int index,int semid)
{
	struct sembuf sop;

	sop.sem_num = index;
	sop.sem_op = -1;
	sop.sem_flg = 0;

	semop(semid,&sop,1);
}

void Voperation(int index,int semid)
{
	struct sembuf sop;

	sop.sem_num = index;
	sop.sem_op = 1;
	sop.sem_flg = 0;

	semop(semid,&sop,1);
}
int main()
{
	key_t key;
	key = ftok(".",123);
	pid_t pid;
	int semid;
	int shmid;
	char *shmaddr;

	semid = semget(key,2,IPC_CREAT|0755);
	if(semid < 0)
	{
		perror("semget");
		return -1;
	}
	shmid = shmget(key,128,IPC_CREAT|0755);
	if(shmid < 0)
	{
		perror("shmget");
		return -2;
	}
	//init semapuore
	union semnum myun;
	//init semaphore read
	myun.val = 0;
	semctl(semid,SEM_READ,SETVAL,myun);
	//init semaphore write
	myun.val = 1;
	semctl(semid,SEM_WRITE,SETVAL,myun);

	pid = fork();
	if(pid == 0)
	{

		shmaddr = (char *)shmat(shmid,NULL,0);
		while(1)
		{
			Poperation(SEM_READ,semid);
			printf("get share memory is:%s\n",shmaddr);
			Voperation(SEM_WRITE,semid);
		}
	}
	if(pid > 0)
	{

		shmaddr = (char *)shmat(shmid,NULL,0);
		while(1)
		{
			Poperation(SEM_WRITE,semid);
			printf("please input to share memory\n");
			fgets(shmaddr,32,stdin);
			Voperation(SEM_READ,semid);
		}
	}
	return 0;
}

union共用体:semctl 初始化专用

  1. 语法:

union共用体:所有成员共用一块内存,这里只存一个 int 值

  1. 知识点:

Linux 规定:用semctl(SETVAL)给信号量设初值,必须传这个共用体

  1. 逻辑:

专门用来装「信号量初始计数器数值」

代码整套逻辑

  • ftok 造一把钥匙 → 信号量 + 共享内存绑定
  • semget 造 2 个红绿灯,shmget 造一块黑板
  • semctl 初始化:写灯亮 (1),读灯灭 (0)
  • fork 拆成父子两人
  • 父:抢写灯→写黑板→开读灯喊子
  • 子:等读灯亮→读黑板→开写灯喊父
  • P = 等牌卡死,V = 放牌唤醒
相关推荐
skywalk816313 分钟前
通过下载Ubuntu ova文件在Virtual Box快速安装ubuntu
linux·运维·ubuntu·virtualbox
wuminyu27 分钟前
JVM锁膨胀与Futex源码解析
java·linux·c语言·jvm·c++
斑马13939 分钟前
Linux软件编程学习笔记(十一)——HTTP协议
linux·笔记·学习
OpenPomeloxCommunity1 小时前
Linux驱动基础(一):模块机制的设计与实现
linux
Shadow(⊙o⊙)1 小时前
Linux网络——文件与网络的连接桥梁struct sock {
linux·运维·网络
新时代牛马1 小时前
Linux 性能调优与追踪完整篇:ftrace、perf、eBPF从采样到落地验证
linux·运维·服务器
sunoo-2291 小时前
【网络编程 + 数据库】select 与 epoll 核心区别详解 + SQLite 入门到 C 接口全攻略
linux·网络·数据库·vscode·学习·sqlite
zbyyd1 小时前
Linux 系统编程 :select/epoll 多路复用与 SQLite 数据库实战
linux·数据库·sqlite
Mortalbreeze1 小时前
深入理解 Linux IO 模型(二):多路复用——select
linux·运维·服务器·网络·tcp/ip
koi77u2 小时前
嵌入式学习———sqlite数据表
linux·数据库·学习·sqlite