操作系统实验六 信号量的实现和应用(哈工大李治军)(二)

简介: 操作系统实验六 信号量的实现和应用(哈工大李治军)(二)

用户程序 pc.c


知识点

文件操作




信号量作用


mutex 是保证互斥访问缓存池

empty 是缓冲池里空位的剩余个数,即空缓冲区数,初始值为n

full 是用来记录当前缓冲池中已经占用的缓冲区个数,初始值为0

代码展示

#define __LIBRARY__
#include <unistd.h>
#include <linux/sem.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/sched.h>
_syscall2(sem_t *,sem_open,const char *,name,unsigned int,value)
_syscall1(int,sem_wait,sem_t *,sem)
_syscall1(int,sem_post,sem_t *,sem)
_syscall1(int,sem_unlink,const char *,name)
const char *FILENAME = "/usr/root/buffer_file";    /* 消费生产的产品存放的缓冲文件的路径 */
const int NR_CONSUMERS = 5;                        /* 消费者的数量 */
const int NR_ITEMS = 50;                        /* 产品的最大量 */
const int BUFFER_SIZE = 10;                        /* 缓冲区大小,表示可同时存在的产品数量 */
sem_t *metux, *full, *empty;                    /* 3个信号量 */
unsigned int item_pro, item_used;                /* 刚生产的产品号;刚消费的产品号 */
int fi, fo;                                        /* 供生产者写入或消费者读取的缓冲文件的句柄 */
int main(int argc, char *argv[])
{
    char *filename;
    int pid;
    int i;
    filename = argc > 1 ? argv[1] : FILENAME;
    /* O_TRUNC 表示:当文件以只读或只写打开时,若文件存在,则将其长度截为0(即清空文件)
     * 0222 和 0444 分别表示文件只写和只读(前面的0是八进制标识)
     */
    fi = open(filename, O_CREAT| O_TRUNC| O_WRONLY, 0222);    /* 以只写方式打开文件给生产者写入产品编号 */
    fo = open(filename, O_TRUNC| O_RDONLY, 0444);            /* 以只读方式打开文件给消费者读出产品编号 */
    metux = sem_open("METUX", 1);    /* 互斥信号量,防止生产消费同时进行 */
    full = sem_open("FULL", 0);        /* 产品剩余信号量,大于0则可消费 */
    empty = sem_open("EMPTY", BUFFER_SIZE);    /* 空信号量,它与产品剩余信号量此消彼长,大于0时生产者才能继续生产 */
    item_pro = 0;
    if ((pid = fork()))    /* 父进程用来执行消费者动作 */
    {
        printf("pid %d:\tproducer created....\n", pid);
        /* printf()输出的信息会先保存到输出缓冲区,并没有马上输出到标准输出(通常为终端控制台)。
         * 为避免偶然因素的影响,我们每次printf()都调用一下stdio.h中的fflush(stdout)
         * 来确保将输出立刻输出到标准输出。
         */
        fflush(stdout);
        while (item_pro <= NR_ITEMS)    /* 生产完所需产品 */
        {
            sem_wait(empty);
            sem_wait(metux);
            /* 生产完一轮产品(文件缓冲区只能容纳BUFFER_SIZE个产品编号)后
             * 将缓冲文件的位置指针重新定位到文件首部。
             */
            if(!(item_pro % BUFFER_SIZE))
                lseek(fi, 0, 0);
            write(fi, (char *) &item_pro, sizeof(item_pro));        /* 写入产品编号 */
            printf("pid %d:\tproduces item %d\n", pid, item_pro);
            fflush(stdout);
            item_pro++;
            sem_post(full);        /* 唤醒消费者进程 */
            sem_post(metux);
        }
    }
    else    /* 子进程来创建消费者 */
    {
        i = NR_CONSUMERS;
        while(i--)
        {
            if(!(pid=fork()))    /* 创建i个消费者进程 */
            {
                pid = getpid();
                printf("pid %d:\tconsumer %d created....\n", pid, NR_CONSUMERS-i);
                fflush(stdout);
                while(1)
                {
                    sem_wait(full);
                    sem_wait(metux);
                    /* read()读到文件末尾时返回0,将文件的位置指针重新定位到文件首部 */
                    if(!read(fo, (char *)&item_used, sizeof(item_used)))
                    {
                        lseek(fo, 0, 0);
                        read(fo, (char *)&item_used, sizeof(item_used));
                    }
                    printf("pid %d:\tconsumer %d consumes item %d\n", pid, NR_CONSUMERS-i+1, item_used);
                    fflush(stdout);
                    sem_post(empty);    /* 唤醒生产者进程 */
                    sem_post(metux);
                    if(item_used == NR_ITEMS)    /* 如果已经消费完最后一个商品,则结束 */
                        goto OK;
                }
            }
        }
    }
OK:
    close(fi);
    close(fo);
    return 0;
}


修改内核


编写 sem.h

文件位置:oslab/linux-0.11/include/linux

#ifndef _SEM_H
#define _SEM_H
#include <linux/sched.h>
#define SEMTABLE_LEN    20
#define SEM_NAME_LEN    20
typedef struct semaphore{
    char name[SEM_NAME_LEN];
    int value;
    struct task_struct *queue;
} sem_t;
extern sem_t semtable[SEMTABLE_LEN];
#endif



编写 sem.c


#include <linux/sem.h>
#include <linux/sched.h>
#include <unistd.h>
#include <asm/segment.h>
#include <linux/tty.h>
#include <linux/kernel.h>
#include <linux/fdreg.h>
#include <asm/system.h>
#include <asm/io.h>
//#include <string.h>
sem_t semtable[SEMTABLE_LEN];
int cnt = 0;
sem_t *sys_sem_open(const char *name,unsigned int value)
{
    char kernelname[100];   
    int isExist = 0;
    int i=0;
    int name_cnt=0;
    while( get_fs_byte(name+name_cnt) != '\0')
    name_cnt++;
    if(name_cnt>SEM_NAME_LEN)
    return NULL;
    for(i=0;i<name_cnt;i++)
    kernelname[i]=get_fs_byte(name+i);
    int name_len = strlen(kernelname);
    int sem_name_len =0;
    sem_t *p=NULL;
    for(i=0;i<cnt;i++)
    {
        sem_name_len = strlen(semtable[i].name);
        if(sem_name_len == name_len)
        {
                if( !strcmp(kernelname,semtable[i].name) )
                {
                    isExist = 1;
                    break;
                }
        }
    }
    if(isExist == 1)
    {
        p=(sem_t*)(&semtable[i]);
        //printk("find previous name!\n");
    }
    else
    {
        i=0;
        for(i=0;i<name_len;i++)
        {
            semtable[cnt].name[i]=kernelname[i];
        }
        semtable[cnt].value = value;
        p=(sem_t*)(&semtable[cnt]);
         //printk("creat name!\n");
        cnt++;
     }
    return p;
}
int sys_sem_wait(sem_t *sem)
{
    cli();
    while( sem->value <= 0 )       
        sleep_on(&(sem->queue));   
    sem->value--;               
    sti();
    return 0;
}
int sys_sem_post(sem_t *sem)
{
    cli();
    sem->value++;
    if( (sem->value) <= 1)
        wake_up(&(sem->queue));
    sti();
    return 0;
}
int sys_sem_unlink(const char *name)
{
    char kernelname[100];  
    int isExist = 0;
    int i=0;
    int name_cnt=0;
    while( get_fs_byte(name+name_cnt) != '\0')
            name_cnt++;
    if(name_cnt>SEM_NAME_LEN)
            return NULL;
    for(i=0;i<name_cnt;i++)
            kernelname[i]=get_fs_byte(name+i);
    int name_len = strlen(name);
    int sem_name_len =0;
    for(i=0;i<cnt;i++)
    {
        sem_name_len = strlen(semtable[i].name);
        if(sem_name_len == name_len)
        {
                if( !strcmp(kernelname,semtable[i].name))
                {
                        isExist = 1;
                        break;
                }
        }
    }
    if(isExist == 1)
    {
        int tmp=0;
        for(tmp=i;tmp<=cnt;tmp++)
        {
            semtable[tmp]=semtable[tmp+1];
        }
        cnt = cnt-1;
        return 0;
    }
    else
        return -1;
}


文件位置:oslab/linux-0.11/kernel


目录
相关文章
|
1天前
|
存储 API 调度
深入理解操作系统:从内核到应用
【6月更文挑战第25天】本文将深入探讨操作系统的内部结构、功能以及它如何与应用程序交互。我们将从内核开始,逐步了解进程管理、内存管理、文件系统等关键组件,并讨论操作系统如何支持多任务处理和并发。最后,我们将探讨操作系统与应用程序之间的接口,以及操作系统如何影响应用程序的性能和稳定性。
|
14天前
|
存储 安全 调度
深入理解操作系统:从基础概念到高级应用
本文将深入探讨操作系统的基本概念、功能和特性,以及其在现代计算环境中的应用。我们将从操作系统的定义和历史开始,然后详细介绍其主要组件和工作原理,包括进程管理、内存管理、文件系统和设备管理等。最后,我们将讨论一些高级主题,如操作系统的安全性、性能优化和虚拟化技术。无论您是计算机科学的学生,还是对操作系统有兴趣的技术人员,这篇文章都将为您提供深入理解和应用操作系统所需的知识和技能。
|
30天前
|
JSON 数据管理 测试技术
自动化测试工具Selenium Grid的深度应用分析深入理解操作系统的内存管理
【5月更文挑战第28天】随着互联网技术的飞速发展,软件测试工作日益复杂化,传统的手工测试已无法满足快速迭代的需求。自动化测试工具Selenium Grid因其分布式执行特性而受到广泛关注。本文旨在深入剖析Selenium Grid的工作原理、配置方法及其在复杂测试场景中的应用优势,为测试工程师提供高效测试解决方案的参考。
|
30天前
|
机器学习/深度学习 传感器 自动驾驶
基于深度学习的图像识别技术在自动驾驶系统中的应用深入理解操作系统内存管理:原理与实践
【5月更文挑战第28天】 随着人工智能技术的飞速发展,图像识别作为其重要分支之一,在多个领域展现出了广泛的应用潜力。尤其是在自动驾驶系统中,基于深度学习的图像识别技术已成为实现车辆环境感知和决策的关键。本文将深入探讨深度学习算法在自动驾驶图像识别中的作用,分析其面临的挑战以及未来的发展趋势,并以此为基础,展望该技术对自动驾驶安全性和效率的影响。
|
1月前
|
机器学习/深度学习 监控 调度
深度学习在图像识别中的应用与挑战深入理解操作系统中的进程调度策略
【5月更文挑战第27天】 随着人工智能技术的飞速发展,深度学习已经成为图像识别领域的核心技术。本文将探讨深度学习在图像识别中的应用,以及在实际应用中所面临的挑战。我们将介绍深度学习的基本原理,以及如何将其应用于图像识别任务中。此外,我们还将讨论在实际应用中可能遇到的一些问题,如数据不平衡、模型过拟合等,并提出相应的解决方案。
|
1月前
|
存储 缓存 算法
深入理解操作系统内存管理:分页系统的优势与挑战构建高效Android应用:探究Kotlin协程的优势与实践
【5月更文挑战第27天】 在现代计算机系统中,内存管理是操作系统的核心功能之一。分页系统作为一种内存管理技术,通过将物理内存划分为固定大小的单元——页面,为每个运行的程序提供独立的虚拟地址空间。这种机制不仅提高了内存的使用效率,还为多任务环境提供了必要的隔离性。然而,分页系统的实现也带来了一系列的挑战,包括页面置换算法的选择、内存抖动问题以及TLB(Translation Lookaside Buffer)的管理等。本文旨在探讨分页系统的原理、优势及其面临的挑战,并通过分析现有解决方案,提出可能的改进措施。
|
1月前
|
C++
【操作系统】信号量机制(整型信号量、记录型信号量),用信号量实现进程互斥、同步、前驱关系
【操作系统】信号量机制(整型信号量、记录型信号量),用信号量实现进程互斥、同步、前驱关系
39 6
|
1月前
|
缓存 算法 Java
操作系统(8)---进程的同步与互斥以及信号量机制(万字总结~)(4)
操作系统(8)---进程的同步与互斥以及信号量机制(万字总结~)
65 0
|
1月前
操作系统(8)---进程的同步与互斥以及信号量机制(万字总结~)(3)
操作系统(8)---进程的同步与互斥以及信号量机制(万字总结~)
54 0
|
1月前
|
C++ 调度
操作系统(8)---进程的同步与互斥以及信号量机制(万字总结~)(2)
操作系统(8)---进程的同步与互斥以及信号量机制(万字总结~)
76 0

热门文章

最新文章