在Linux0.11实现信号量
一、安装虚拟机步骤(64位)
1.下载Vmware Workstation Pro
下载地址
2.下载安装,安装位置最好可以放在SSD盘
3.取消勾选产品更新和体验计划,后面基本都是下一步
二、安装Ubuntu(64位)
1.下载Ubuntu镜像文件。地址 选择下载第一个 Ubuntu桌面版
2.下载完成后,打开Vmware Workstation点击创建虚拟机
3.按照图片进行创建Linux虚拟机
1.点击开启此虚拟机。会开始安装,需要等待一段时间。
如果你显示无法开启,要开启CPU虚拟功能,需要进到bios里开启。进入BIOS后,找到Configuration选项,选择Intel Virtual Technology并回车,将光标移至Enabled,然后再回车,最后按F10保存并退出。
拉到最下面,选择安装中文。然后选择安装Ubuntu。
按如图选择,可能会加载一段时间。
继续一步,选择时区-shanghai
添加用户名和密码(账号名随意,密码设置1就可以),选择自动登录,然后等待安装(时间会有些长)。
三、设置Ubuntu
安装完成后,进入系统设置,基本选择跳过。
1.安装Vmware Tool文件(方便你进行文件传送和 调整视窗大小) 教程
2.设置Root用户
3.换更新源
sudo apt-get upgrade
sudo apt-get update
4.常用命令
1.sudo 管理员执行接下来的命令操作
2.cd 跳转到某某目录 比如 cd oslab cd - 返回上次目录 cd …/ 返回上一层目录
3.
apt-get install 安装软件包apt-get update 更新软件包apt-file search 寻找所要的软件包tar zxf 解压文件
5.安装oslab(实验环境)
hit-oslab
gcc
下载hit-oslab-linux-20110823.tar 直接移动到ubuntu界面主目录上
下载gcc-3.4-ubuntu.tar.gz到tmp目录(在根目录上创建)
利用Shift+ctrl+p 打开终端用该命令解压
tar zxf hit-oslab-linux-20110823.tar.gz
6.安装GCC
用下列命令安装
cd /tmp
tar zxvf gcc-3.4-ubuntu.tar.gz//如果这步不能解压 点右上角重启一遍Ubuntu**
cd gcc-3.4
sudo ./inst.sh xxxx #xxxx换为i386(32位使用)或amd64(64位使用)
然后执行下列命令确保其它必备工具已安装:
sudo apt-get install build-essential bin86 manpages-dev
如果使用的是64位的系统,还要:
sudo apt-get install libc6-dev-i386 ia32-libs ia32-libs-gtk
若出现以下问题则说明有个软件包没安装上,使用sudo apt-get install lib32z1
7. 运行前的配置操作
执行以下命令
1.cd oslab/linux-0.11
2.输入 make
可能会出现以下情况,则是安装gcc未完全,使用sudo apt-get install gcc-multilib
出现sync则说明编译成功
3.接下来跳到oslab目录,你可以使用 cd -命令 或者 cd …/
执行 ./run ,很不幸你会发现又有错误
执行下列命令
sudo apt install libsm6:i386
sudo apt install libx11-6:i386
sudo apt install libxpm4:i386
如果你还缺少软件安装包,
sudo apt-get install apt-file
sudo apt-file update
sudo apt-file search 相关的包 比如上面就搜索 apt-file search libSM.so.6 根据返回信息用安装命令安装
确保你在oslab目录下,再次使用./run 出现以下界面则大功告成。
四、在Linux0.11下实现信号量和应用
想在Linux下实现信号量,就要添加系统调用,一般思路是
• 应用程序调用库函数(API);
• API 将系统调用号存入 EAX,然后通过中断调用使系统进入内核态;
• 内核中的中断处理函数根据系统调用号,调用对应的内核函数(系统调用);
• 系统调用完成相应功能,将返回值存入 EAX,返回到中断处理函数;
• 中断处理函数返回到 API 中;
• API 将 EAX 返回给应用程序。
#define _syscall1(type,name,atype,a) \
type name(atype a) \
{ \
long __res; \ //定义了长整数res
__asm__ volatile ("int $0x80" \ : "=a" (__res) \ //eax将eax的值给res : "0" (__NR_##name),"b" ((long)(a))); \ //NR_name为系统调用号 “0”为默认相当于上面eax将//系统调用号给eax (a)等于第二参数 fd 给ebx
if (__res >= 0) \ //它先将宏 __NR_name 存入 EAX,将参数 fd 存入 EBX
return (type) __res; \ //然后进行0x80 中断调用。调用返回后,从 EAX 取出返回值,存入 __res
errno = -__res; \ //再通过对 __res 的判断决定传给 API 的调用者什么样的返回值
return -1; \
}
1.实现信号量的系统调用(默认在oslab/linux-0.11)
1.在include/unistd.h中添加系统调用编号:
#define __NR_sem_open 72
#define __NR_sem_wait 73
#define __NR_sem_post 74
#define __NR_sem_unlink 75
2.将kernel/system_call.s中的系统调用数修改为76
nr_system_calls = 76
3.在include/linux修改sys.h增加4个函数
extern int sys_sem_open();
extern int sys_sem_wait();
extern int sys_sem_post();
extern int sys_sem_unlink();sys_sem_open,sys_sem_wait,sys_sem_post,sys_sem_unlink
4.修改kernel目录下的Makefile
OBJS = sched.o system_call.o traps.o asm.o fork.o \
panic.o printk.o vsprintf.o sys.o exit.o \
signal.o mktime.o sem.o
......### Dependencies:sem.s sem.o: sem.c ../include/linux/sem.h ../include/linux/kernel.h \
../include/unistd.h
5.include/linux目录下新建sem.h,定义信号量的数据结构
#ifndef _SEM_H
#define _SEM_H
#include <linux/sched.h>#define SEMTABLE_LEN 20
#define SEM_NAME_LEN 20typedef struct semaphore{char name[SEM_NAME_LEN];int value;struct task_struct *queue;
} sem_t;
extern sem_t semtable[SEMTABLE_LEN];#endif
6.在kernel目录下,创建sem.c并实现其功能
int sem_open(const char *name, unsigned int value);
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);
int sem_unlink(const char *name);
P()
{cli();//关中断//遍历阻塞队列所有被唤醒的进程中分配了信号量的,也就是!=0的while(sem->value == 0) //参考Liunx完全注释和哈工大课程{//则将当前进程加入到阻塞队列schedule();}sem->value--;sti();//开中断
}V()
{cli();//关中断sem->value++;//让阻塞队列中所有进程全部被唤醒,也就是变成就绪态,进入就绪队列//if 阻塞队列中没有进程 就不需要做啥sti();//开中断
}
7.实现生产者消费者pc.c
producer()
{p(empty);//empty--,看是不是要阻塞(生产者进程)p(mutex);//mutex--,看是不是可以进入临界区(此处对应共享缓冲区-也就是文件)//向缓冲区(共享文件)中写入数据v(mutex);//mutex++,出了临界区,需要mutex++,以便下一次可以进入v(full);//full++,看是不是要唤醒(消费者进程)
}
//消费者进程:
consumer()
{p(full);//full--,看是不是要阻塞(消费者进程)p(mutex);//mutex--,看是不是可以进入临界区(此处对应共享缓冲区-也就是文件)//向缓冲区(共享文件)中写入数据v(mutex);//mutex++,出了临界区,需要mutex++,以便下一次可以进入v(empty);//empty++,看是不是要唤醒(生产者进程)
}
8.挂载虚拟硬盘
在oslab目录下使用挂载命令
将unistd.h复制到usr/include下,将sem.h和sys.h复制到usr/include/linux下,将pc放入usr/root下。
挂载命令sudo ./mount-hdc
卸载命令sudo umount hdc
注意1:不要在0.11内核运行的时候mount镜像文件,否则可能会损坏文件系统。同理,也不要在已经mount的时候运行0.11内核(挂载时候,要推出linux0.11)
注意2:在关闭Bochs之前,需要先在0.11的命令行运行“sync”,确保所有缓存数据都存盘后,再关闭Bochs(每次编译运行后用sync保存)
9.结果
在linux0.11下使用
gcc -o pc pc.c
./pc 结果即可输出
如果出现乱码,可以把结果转换成文件挂载移出到Ubuntu下查看或者直接用less命令打开
./pc > output.txt
less output.txt
五、 参考文档
1.实验手册
2.操作系统 B站链接
3.《Linux完全注释》
在Linux0.11实现信号量相关推荐
- linux0.11—内存管理实验
实验基本内容 用 Bochs 调试工具跟踪 Linux 0.11 的地址翻译(地址映射)过程,了解 IA-32 和 Linux 0.11 的内存管理机制: 在 Ubuntu 上编写多进程的生产者-消费 ...
- Linux0.11内核引导启动过程概述
Linux0.11仅支持x86架构.它的内核引导启动程序在文件夹boot内,共有三个汇编代码文件.按照启动流程依次是: (1)bootsect.s.boot是启动引导的意思,sect即sector,是 ...
- linux0.11内核编译,编译Linux-0.11内核
make[1]:正在离开目录 `/home/guang/temp/h/linux-0.11/lib' kernel/kernel.o: In function `number': /home/guan ...
- c 取地址 虚拟地址 物理地址_通过linux0.11源码理解进程的虚拟地址、线性地址、物理地址...
进程的地址有三种,分别是虚拟地址(逻辑地址).线性地址.物理地址.在分析之前先讲一下进程执行的时候,地址的解析过程.在保护模式下,段寄存器保存的是段选择子,当进程被系统选中执行时,会把tss和ldt等 ...
- Linux0.11小结
第一部分 基础内容 1.操作系统基础 操作系统是计算机硬件系统与用户程序间重要环节,理解操作系统的原理是编写优秀代码的基础.教课书中阐述的操作系统一般由5部分组成. 一个最简单的操作系统,可以 ...
- Linux0.11启动过程
从开机加电,到执行main函数之前的过程 好吧,这里应该是有执行3个汇编的文件,但是我不太了解.囧 从main函数,到启动OK(即可以响应用户操作了) 这个步骤做了3件事情: 创建进程0,使之具备在主 ...
- Linux0.11进程切换和TSS结构
TSS 全称为task state segment,是指在操作系统进程管理的过程中,进程切换时的任务现场信息. X86体系从硬件上支持任务间的切换.为此目的,它增设了一个新段:任务状态段( ...
- 对Linux0.11 中 进程0 和 进程1分析
1. 背景 进程的创建过程无疑是最重要的操作系统处理过程之一,很多书和教材上说的最多的还是一些原理的部分,忽略了很多细节.比如,子进程复制父进程所拥有的资源,或者子进程和父进程共享相同的物理页面,拥有 ...
- 搭建Linux0.11系统环境
学习Linux0.11内核源代码,我们需要搭建一个基于Linux0.11的操作平台: 1) boch仿真器:可以从http://bochs.sourceforg ...
最新文章
- 脑机接口,风口还是入口?
- JAVA实现斐波那契数列问题(《剑指offer》)
- SQLite大批量插入性能优化
- linux删除指定端口的进程
- crv仪表上的i是什么指示灯_汽车打不着火是怎么回事,仪表盘汽车发动机故障灯亮是什么情况故障指示灯图解大全集...
- 老李分享:持续集成学好jenkins之Git和Maven配置
- Rails secret token bug
- 花生壳+FileZilla搭建公网FTP服务器
- 凯利公式和复利公式,与概率和时间为友
- 蓝牙电话之HFP-通话
- 串口通信 数据采集软件 上位机 数据采集软件,可以采集plc,串口通信设备,tcp通信设备的数据
- python刷网易云_Python脚本用于定时关闭网易云音乐PC客户端
- springboot整合分布式任务调度 elastic-job
- 计算机jsp外文文献,JSP英文参考文献
- VM虚拟机 .vmdk文件,拆分多个文件,合并单个文件
- 温控中使用PID控制算法
- MATLAB图像的两种模糊模式
- 练习-Java字符串之StringToKenizer类分割字符串之计算手机话费总额
- oralce启动问题You may need to set ORACLE_HOME to your Oracle software directory
- 使用Nginx访问图片报404