信号量的实现和应用

此实验最难的地方:读了文件的数字以后怎么记录哪些读过
参考
我在内核态加了一个consumption变量和两个用于读/写consumption的系统调用.
遇到的坑:sem.h make以后复制才行
不能在用户态下访问内核态的内存.,所以我一开始不知道怎么停止消费者进程,
比较有趣的地方:把把int型变量的地址强行转化为char*类型,对其每一个字节进行操作.进程休眠和唤醒队列我用的是显式队列
主程序

#define __LIBRARY__
#include <stdio.h>/*sprintf,printf\u5934\u6587\u4EF6*/
#include <unistd.h>/*open\u51FD\u6570,read\u51FD\u6570,getpid*/
#include<fcntl.h>/*open\u51FD\u6570mode\u4EE3\u7801*/
#include<sys/types.h>/*\u8FD9\u91CC\u63D0\u4F9B\u7C7B\u578Bpid_t\u548Csize_t\u7684\u5B9A\u4E49*/
#include<asm/system.h>/*cli,sti*/
#include<linux/sem.h>
#include<sys/stat.h>
_syscall2(struct sem_t*, sem_open, const char*, name, unsigned int, value);
_syscall1(int, sem_wait, struct sem_t*, sem);
_syscall1(int, sem_post, struct sem_t*, sem);
_syscall1(int, sem_unlink, const char*, name)
_syscall1(int, read_consumption, char*, data)
_syscall1(int, write_consumption, char*, data)
int fp;/*\u6587\u4EF6\u5168\u5C40\u53D8\u91CF*/
void produce();/*\u751F\u4EA7\u8005\u8FDB\u7A0B*/
void customer();/*\u6D88\u8D39\u8005\u8FDB\u7A0B*/
void produce()/*\u751F\u4EA7\u8005\u8FDB\u7A0B*/
{
	int item = 0;
	int position = 0;/*\u5199\u5165\u4F4D\u7F6E*/
	struct sem_t* empty = (struct sem_t*)sem_open("empty", 0);
	struct sem_t* mutex = (struct sem_t*)sem_open("mutex", 0);
	struct sem_t* full = (struct sem_t*)sem_open("full", 0);
	struct sem_t* stop = (struct sem_t*)sem_open("stop", 0);
	while (item != 500)
	{
		sem_wait(empty);
		sem_wait(mutex);/*\u522B\u7684\u8FDB\u7A0B\u4E0D\u80FD\u8FDB\u5165*/
		position = item % 10;/*\u83B7\u5F97\u5199\u5165\u4F4D\u7F6E*/
		lseek(fp, position * sizeof(int), SEEK_SET);/*\u8BFB\u5199\u6307\u9488\u5230\u6587\u4EF6\u771F\u6B63\u7684\u5C3E\u90E8*/
		write(fp, (char*)(&item), sizeof(int));
		item++;
		sem_post(mutex);
		sem_post(full);

	}



}
void customer()/*\u6D88\u8D39\u8005\u8FDB\u7A0B*/
{
	struct sem_t* stop = (struct sem_t*)sem_open("stop", 1);
	struct sem_t* empty = (struct sem_t*)sem_open("empty", 0);
	struct sem_t* mutex = (struct sem_t*)sem_open("mutex", 0);
	struct sem_t* full = (struct sem_t*)sem_open("full", 0);
	int pid = getpid();
	int position = 0;
	int consumption;
	while (1)
	{
		sem_wait(full);
		sem_wait(mutex);/*\u5176\u4ED6\u8FDB\u7A0B\u4E0D\u80FD\u8FDB\u5165*/
		read_consumption((char*)(&consumption));/*\u83B7\u5F97\u4E0A\u4E00\u6B21\u6D88\u8D39*/
		if (consumption >= 499)/*\u5176\u4F59\u8FDB\u7A0B*/
		{
			sem_post(full);
			printf("quitid=%d\n", pid);
			fflush(stdout);
			sem_post(mutex);
			break;
		}
		position = (consumption + 1) % 10;
		lseek(fp, position * sizeof(int), SEEK_SET);
		read(fp, (char*)(&consumption), sizeof(int));
		write_consumption((char*)(&consumption));
		printf("%d: %d\n", pid, consumption);
		fflush(stdout);
		if (consumption >= 499)/*\u6D88\u8D39499\u7684\u8FDB\u7A0B*/
		{
			sem_post(full);
			printf("499quitid=%d\n", pid);
			fflush(stdout);
			sem_post(mutex);
			break;
		}
		sem_post(mutex);
		sem_post(empty);
	}
}
int main()
{

	struct sem_t* full = (struct sem_t*)sem_open("full", 0);
	struct sem_t* empty = (struct sem_t*)sem_open("empty", 10);
	struct sem_t* mutex = (struct sem_t*)sem_open("mutex", 1);
	struct sem_t* stop = (struct sem_t*)sem_open("stop", 1);
	int pid;
	int i = 0;
	fp = open("market.txt", O_CREAT | O_RDWR | O_TRUNC, 0666);
	if (!(pid = fork()))
	{
		produce();
		return 0;
	}
	for (i = 0; i < 5; i++)
	{
		if (!(pid = fork()))
		{
			customer();
			return 0;
		}
	}
	close(fp);
	return 0;
}```

sem.h:

```c
#include<linux/sched.h>
struct sem_t
{
	int value;/*\u4FE1\u53F7\u91CF\u7684\u503C*/
	struct task_struct* queue[10];/*\u961F\u5217\u7528\u4E8E\u5B58\u653E\u963B\u585E\u6001\u8FDB\u7A0B*/
	char name[10];/*\u4FE1\u53F7\u91CF\u540D\u79F0*/
	int front;//\u961F\u5934
	int rear;//\u961F\u5C3E
};

sem.c

#include<asm/system.h>
#include<linux/kernel.h>
#include<asm/segment.h>
#include<linux/sem.h>
struct sem_t semTable[10];/*\u7528\u4E8E\u5B58\u653E\u4FE1\u53F7\u91CF*/
int tableSize = 0;/*\u6570\u7EC4\u5927\u5C0F*/
int consumption=-1;
int strcmp2(char* str1, char* str2)/*\u5B57\u7B26\u4E32\u6BD4\u8F83\u51FD\u6570*/
{
	int i = 0;
	while (str1[i] != 0 && str2[i] != 0)/*\u4E0D\u8D8A\u754C\u8BBF\u95EE*/
	{
		if (str1[i] != str2[i])
		{
			return 0;/*\u5B57\u7B26\u4E32\u4E0D\u4E00\u6837*/
		}
		else
		{
			i++;
		}
	}
	if (str1[i] != 0 || str2[i] != 0)/*\u53EA\u662F\u5176\u4E2D\u4E00\u4E2A\u5230\u4E86\u7EC8\u70B9*/
	{
		return 0;
	}
	return 1;
}
void strcpy2(char* str1, char* str2)/*\u628Astr1\u91CC\u7684\u590D\u5236\u5230str2*/
{
	int i = 0;
	for (i = 0; str1[i] != 0; i++)
	{
		str2[i] = str1[i];
	}
	str2[i] = 0;
}
struct sem_t* sys_sem_open(const char* name, unsigned int value)/*\u5BFB\u627E/\u521B\u5EFA\u4FE1\u53F7\u91CF\u8FD4\u56DE\u6307\u5411\u4FE1\u53F7\u91CF\u7684\u6307\u9488*/
{
	int i = 0;
	char kernelName[10];/*\u4FE1\u53F7\u91CF\u540D\u79F0*/
	for (i = 0; get_fs_byte(name + i) != 0; i++)/*\u5C06\u5B57\u7B26\u4E32\u4ECE\u7528\u6237\u6001\u62F7\u8D1D\u5230\u5185\u6838\u6001*/
	{
		kernelName[i] = get_fs_byte(name + i);
	}
	kernelName[i] = get_fs_byte(name + i);

	for (i = 0; i < tableSize; i++)
	{
		if (strcmp2(kernelName, semTable[i].name))
		{
			return (struct sem_t*) (&semTable[i]);/*\u540D\u79F0\u4E00\u6837\u8FD4\u56DE\u5730\u5740*/
		}
	}
	tableSize++;
	semTable[tableSize - 1].value = value;/*\u4FE1\u53F7\u91CF\u7684\u503C*/
	strcpy2(kernelName, semTable[tableSize - 1].name);
	semTable[tableSize - 1].front = 0;
	semTable[tableSize - 1].rear = 0;
	return (struct sem_t*)(&semTable[tableSize - 1]);

}
int sys_sem_wait(struct sem_t* sem)
{
	cli();
	sem->value--;
	if ((sem->value) < 0)
	{
		current->state = TASK_UNINTERRUPTIBLE;/*\u7761\u7720*/
		sem->rear = (sem->rear + 1) % (10);
		sem->queue[sem->rear] = current;
		schedule();/*\u6CA1\u6709\u8D44\u6E90\u4EE5\u540E\u5207\u6362\u5230\u522B\u7684\u8FDB\u7A0B*/
	}
	sti();
	return 1;
}
int sys_sem_post(struct sem_t* sem)
{
	cli();
	sem->value++;
	if ((sem->value) <= 0)
	{
		sem->front = (sem->front + 1) % 10;
		sem->queue[sem->front]->state = TASK_RUNNING;/*\u6FC0\u6D3B*/
	}
	sti();
	return 1;
}
int sys_sem_unlock(const char* name)
{
	int i = 0;
	int ptr = 0;
	char kernelName[10];/*\u4FE1\u53F7\u91CF\u540D\u79F0*/
	for (i = 0; get_fs_byte(name + i) != 0; i++)/*\u5C06\u5B57\u7B26\u4E32\u4ECE\u7528\u6237\u6001\u62F7\u8D1D\u5230\u5185\u6838\u6001*/
	{
		kernelName[i] = get_fs_byte(name + i);
	}
	kernelName[i] = get_fs_byte(name + i);
	for (i = 0; i < tableSize; i++)
	{
		if (strcmp2(kernelName, semTable[i].name))
		{
			break;
		}
	}
	for (ptr = i + 1; ptr < tableSize; ptr++)
	{
		semTable[ptr - 1] = semTable[ptr];
	}
	return 1;
}
int sys_read_consumption(char*data)/*\u5C06\u6D88\u8017\u91CF\u8BFB\u5165data*/
{
	int i = 0;
	char* tmp=(char*)(&consumption);
	for (i = 0; i < 4; i++)
	{
		put_fs_byte(tmp[i], data+i);
	}
	return 1;
}
int sys_write_consumption(char* data)/*\u5C06\u6D88\u8017\u91CF\u5199\u5165consumption*/
{
	int i = 0;
	char* tmp = (char*)(&consumption);
	for (i = 0; i < 4; i++)
	{
		tmp[i] = get_fs_byte(data + i);
	}
	return 1;
}

隐式队列
在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值