学习IO的第八天

作业:使用信号灯循环输出ABC

sem.c

#include <head.h>

union semun {
	int              val;    /* Value for SETVAL */
	struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
	unsigned short  *array;  /* Array for GETALL, SETALL */
	struct seminfo  *__buf;  /* Buffer for IPC_INFO
								(Linux-specific) */
};


//初始化函数
int init_sem(int semid, int semno)
{
	int val = -1;
	printf("请输入编号为%d的灯的初始值:", semno);
	scanf("%d", &val);
	getchar();     //吸收scanf留下的回车

	//对当前灯进行赋初始值
	//定义一个共用体变量
	union semun us;
	us.val = val;           //要赋的值
	if(semctl(semid, semno, SETVAL, us) == -1)
	{
		perror("semctl error\n");
		return -1;
	}


	//成功返回0
	return 0;
}


//信号灯集的申请,初始化信号灯,并返回信号灯集的id
int create_sem(int semcount)
{
	//1.创建key值
	key_t key = ftok("/", 'y');
	if(key == -1)
	{
		perror("ftok error\n");
		return -1;
	}

	//2.通过key值创建一个信号灯集
	int semid = semget(key, semcount, IPC_CREAT|IPC_EXCL|0664);
	if(semid == -1)
	{
		if(errno == EEXIST)
		{
			//信号灯集已经存在,无需创建直接打开即可
			semid = semget(key, semcount, IPC_CREAT);
			return semid;            //之后的进程打开信号灯集只需返回id即可,无需进行初始化操作
		}

		perror("semget error\n");
		return -1;
	}

	//3.给信号灯集中的信号灯进行初始化操作
	for(int i=0;i<semcount;i++)
	{
		init_sem(semid, i);         //初始化编号为i的灯value值
	}

	//4.返回信号灯集的id
	return semid;
}

//申请信号灯资源操作P操作
int P(int semid, int semno)
{
	//定一个操作的结构体变量
	struct sembuf buf;
	buf.sem_num = semno;      //要操作的灯的编号
	buf.sem_op = -1;          //表示申请资源操作
	buf.sem_flg = 0;          //如果没有资源,则阻塞等待

	//调用semop函数完成P操作
	if(semop(semid, &buf, 1) == -1)
	{
		perror("semop error\n");
		return -1;
	}

	return 0;       //成功返回0
}

//释放信号灯资源操作 v操作
int V(int semid, int semno)
{
	//定一个操作的结构体变量
	struct sembuf buf;
	buf.sem_num = semno;      //要操作的灯的编号
	buf.sem_op = 1;          //表示释放资源操作
	buf.sem_flg = 0;          //如果没有资源,则阻塞等待

	//调用semop函数完成V操作
	if(semop(semid, &buf, 1) == -1)
	{
		perror("semop error\n");
		return -1;
	}

	return 0;       //成功返回0

}

//信号灯集的删除
int del_sem(int semid)
{
	if(semctl(semid, 0, IPC_RMID, 0) == -1)
	{
		perror("del error\n");
		return -1;
	}

	return 0;
}



主函数

#include <head.h>
#include "sem.h"

#define PAGE_SIZE 4096

int main(int argc, const char *argv[])
{
	//创建一个信号灯集
	int semid = create_sem(3);       //创建一个信号灯集包含两个灯,并初始化
	if(semid == -1)
	{
		perror("create_sem error\n");
		return -1;
	}

	//创建的key值
	key_t key = ftok("/", 'y');
	if(key == -1)
	{
		perror("ftok error\n");
		return -1;
	}
	printf("key = %#x\n", key);

	//通过key值创建共享内存段
	int shmid = shmget(key, PAGE_SIZE, IPC_CREAT|0664);
	if(shmid == -1)
	{
		perror("shmget error\n");
		return -1;
	}
	printf("shmid = %d\n", shmid);

	//将共享内存段映射到用户空间
	char *addr = (char *)shmat(shmid, NULL, 0);

	if(addr == (void *)-1)
	{
		perror("shmat error\n");
		return -1;
	}
	printf("addr = %p\n", addr);     //输出映射的虚拟地址

	pid_t pid = -1;
	
	pid = fork();

	if(pid > 0)
	{
		pid_t pid2 = fork();
		if(pid2 > 0)
		{
			//父进程

			int count =0;
			while(1)
			{
				//V操作,释放1灯的资源				
				P(semid,0);
			
				printf("A");
				count++;
				fflush(stdout);    //每个进程的用户空间相互独立,缓冲区不同
				
				V(semid,1);
				if(count == 5)
				{
					break;
				}
			}	
			wait(NULL);
			wait(NULL);
			wait(NULL);
		}
		else if(pid2 == 0)
		{
			//子进程2
			int count=0;
			while(1)
			{
				//P操作,等待0灯的资源
				P(semid, 2);

				printf("C\n");
				count++;
				V(semid, 0);

				if(count == 5)
				{
				break;
				}

			}
			exit(EXIT_SUCCESS);

		}
		else
		{
			perror("fork2 error\n");

			return -1;
		}
	}
	else if(pid == 0)
	{
		//子进程1
		int count=0;
		while(1)
		{
			//P操作,等待1号灯的资源
			P(semid, 1);

			printf("B");
			count++;
			fflush(stdout);
			//V操作,释放0号灯的资源
			V(semid,2);

			if(count == 5)
			{
				break;
			}

		}
		exit(EXIT_SUCCESS);
	}
	else 
	{
		perror("fork1 error\n");
		return -1;
	}

	if(shmdt(addr) == -1)
	{
		perror("shmdt error\n");
		return -1;
	}

	del_sem(semid);

	return 0;
}

现象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/239270.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

InnoDB在SQL查询中的关键功能和优化策略

文章目录 前言存储引擎介绍存储引擎是干嘛的InnoDB的体系结构 InnoDB的查询操作InnoDB的查询原理引入 Buffer Pool引入数据页Buffer Pool 的结构数据页的加载Buffer Pool 的管理Buffer Pool 的优化 总结 前言 通过上篇文章《MySQL的体系结构与SQL的执行流程》了解了SQL语句的执…

IO第二天作业

1.用read write函数实现文件拷贝 程序 #include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h> #include <stdlib.h> #include <string.h>int main(int argc, const char *argv[]){…

孩子还是有一颗网安梦——Bandit通关教程:Level 9 → Level 10

&#x1f575;️‍♂️ 专栏《解密游戏-Bandit》 &#x1f310; 游戏官网&#xff1a; Bandit游戏 &#x1f3ae; 游戏简介&#xff1a; Bandit游戏专为网络安全初学者设计&#xff0c;通过一系列级别挑战玩家&#xff0c;从Level0开始&#xff0c;逐步学习基础命令行和安全概念…

初学编程100个代码,python 基础 详细

本篇文章给大家谈谈初学编程100个代码&#xff0c;以及python 基础 详细&#xff0c;希望对各位有所帮助&#xff0c;不要忘了收藏本站喔。 1.Python标识符 在 Python 里&#xff0c;标识符有字母、数字、下划线组成。 在 Python 中&#xff0c;所有标识符可以包括英文、数字以…

新版Spring Security6.2架构 (二) - Authentication

前言&#xff1a; 书接上文&#xff0c;继续官网的个人翻译和个人理解&#xff0c;有不对的请见谅。第一个篇博客中写到Sevlet appliation的总体架构&#xff0c;本博客是写Sevlet appliation中Authentication的架构&#xff0c;在后面第三篇博客将会写到新版spring security如…

IO流(一)

目录 一.关于IO流 二.字节流 1.FIleOutputStream&#xff08;字节输出流&#xff09; 1.书写步骤&#xff1a; 1.创建字节输出流对象 2.写数据 3.释放资源 2.书写数据的三种方式 3.换行写入数据&#xff1a; 4.续写 2.FileInputStream&#xff08;字节输入流&#xf…

【算法-字符串3】听说KMP很难?进来看这篇:实现strstr(),查找子串

今天&#xff0c;带来KMP算法的讲解。文中不足错漏之处望请斧正&#xff01; 理论基础点这里 今天我们来实现strstr()。 题意转化 在一个字符串mainStr中找另一个字符串subStr。 解决思路 两指针i和j分别在mainStr和subStr中拿取字符尝试匹配 匹配&#xff1a;继续不匹配&…

HTML实现页面

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>工商银行电子汇款单</title> </head> &…

主机访问Android模拟器网络服务方法

0x00 背景 因为公司的一个手机app的开发需求&#xff0c;要尝试链接手机开启的web服务。于是在Android Studio的Android模拟器上尝试连接&#xff0c;发现谷歌给模拟器做了网络限制&#xff0c;不能直接连接。当然这个限制似乎从很久以前就存在了。一直没有注意到。 0x01 And…

回顾【数学基础】找出断层,继续前进, 使用chatGPT学习并解决实际问题:微积分

已经学过的算术、代数、几何。跳过。 从微积分开始 想象一下&#xff0c;你在画一条曲线&#xff0c;或者在一个大草地上奔跑。微积分就是一种数学工具&#xff0c;帮助我们了解这条曲线的形状&#xff0c;或者你奔跑的方式。 微分&#xff08;就像研究曲线上的每一小点&…

SQL基础理论篇(十一):事务隔离

文章目录 简介事务并发时的常见异常什么是脏读&#xff1f;什么是不可重复读&#xff1f;什么是幻读&#xff1f; 事务的常用隔离级别参考文献 简介 之前我们讲过事务的四大特性&#xff0c;即ACID&#xff0c;分别是原子性、一致性、隔离性和持久性。隔离性就是事务的基本特性…

ROBdispatch stage

ROB会跟踪所有pipeline中的指令的状态&#xff1b;一旦ROB中&#xff0c;header指的entry complete了&#xff0c;则该指令可以commit,其architectural state属于visible了&#xff1b;如果header instruction 发生了异常&#xff0c;pipleine需要flush, 在该exception instruc…

Python接口自动化测试 —— Requests库学习

安装&#xff1a; pip install requests 例子&#xff1a; import requests r requests.get(http://www.baidu.com) print r.status_code print type(r) print r.cookies运行程序&#xff0c;得到结果&#xff1a; 运行程序&#xff0c;得到结果&#xff1a; 200 <…

Leetcode—2963.统计好分割方案的数目【困难】

2023每日刷题&#xff08;五十七&#xff09; Leetcode—2963.统计好分割方案的数目 算法思想 参考灵神思路 实现代码 class Solution { public:long long mod 1e97;long long pow(long long x, int cnt) {if(cnt 0) {return 1;}if(cnt 1) {return x % mod;}long long …

css处理 纯英文数据不换行问题 - word-break、word-wrap

问题图 解决 添加 css 样式 word-break: break-all;补充 还有一个 word-wrap 样式&#xff0c;可以看下 参考 &#xff1a; word-wrap: normal 只在允许的断字点换行&#xff08;浏览器保持默认处理&#xff09;。word-wrap: break-word 在长单词或 URL 地址内部进行换行。

书-选择排序法P156

#include<stdio.h> int main(){int b[5]{8,2,6,3,7};int i , j ,k ;for(i0;i<4;i){for(ji1;j<5;j)if(b[i]<b[j]){kb[i];b[i]b[j];b[j]k;} }for(i0;i<5;i)printf("%d ",b[i]); return 0; }选择排序&#xff1a;就是自己跟下一个比较&#xff0c;然后…

Android studio 无法查看源码

Android studio 查看源码时提示 Decompiled .class file,bytecode version:52.0(java 8) 1、检查 buildToolsVersion 2、检查相关资源文件

SPRD Android 13 下拉状态栏菜单添加静音快捷键简单记录

SPRD Android 13 下拉状态栏菜单添加静音快捷键简单记录 需要修改文件具体修改补丁吐槽需要修改文件 frameworks/base/packages/SystemUI/res/values/config.xml frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java frameworks/base…

1844_高边驱动以及低边驱动的选择

Grey 全部学习内容汇总&#xff1a;GitHub - GreyZhang/g_hardware_basic: You should learn some hardware design knowledge in case hardware engineer would ask you to prove your software is right when their hardware design is wrong! 1844_高边驱动以及低边驱动的…

mmpi量表在各企事业单位 入职体检中的应用

mmpi量表主要应用在医院精神科门诊中&#xff0c;用来检测筛查精神类疾病&#xff0c;比如&#xff1a;焦虑抑郁&#xff0c;疑病妄想强迫性、精神分裂、精神病态、社会内向性、癔症&#xff0c;精神衰弱&#xff0c;躁狂等等。 民航&#xff0c;司法&#xff0c;军警&#xf…