此实验最难的地方:读了文件的数字以后怎么记录哪些读过
参考
我在内核态加了一个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;
}
隐式队列