一、安装虚拟机步骤(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实现信号量相关推荐

  1. linux0.11—内存管理实验

    实验基本内容 用 Bochs 调试工具跟踪 Linux 0.11 的地址翻译(地址映射)过程,了解 IA-32 和 Linux 0.11 的内存管理机制: 在 Ubuntu 上编写多进程的生产者-消费 ...

  2. Linux0.11内核引导启动过程概述

    Linux0.11仅支持x86架构.它的内核引导启动程序在文件夹boot内,共有三个汇编代码文件.按照启动流程依次是: (1)bootsect.s.boot是启动引导的意思,sect即sector,是 ...

  3. linux0.11内核编译,编译Linux-0.11内核

    make[1]:正在离开目录 `/home/guang/temp/h/linux-0.11/lib' kernel/kernel.o: In function `number': /home/guan ...

  4. c 取地址 虚拟地址 物理地址_通过linux0.11源码理解进程的虚拟地址、线性地址、物理地址...

    进程的地址有三种,分别是虚拟地址(逻辑地址).线性地址.物理地址.在分析之前先讲一下进程执行的时候,地址的解析过程.在保护模式下,段寄存器保存的是段选择子,当进程被系统选中执行时,会把tss和ldt等 ...

  5. Linux0.11小结

    第一部分 基础内容 1.操作系统基础     操作系统是计算机硬件系统与用户程序间重要环节,理解操作系统的原理是编写优秀代码的基础.教课书中阐述的操作系统一般由5部分组成. 一个最简单的操作系统,可以 ...

  6. Linux0.11启动过程

    从开机加电,到执行main函数之前的过程 好吧,这里应该是有执行3个汇编的文件,但是我不太了解.囧 从main函数,到启动OK(即可以响应用户操作了) 这个步骤做了3件事情: 创建进程0,使之具备在主 ...

  7. Linux0.11进程切换和TSS结构

    TSS 全称为task state segment,是指在操作系统进程管理的过程中,进程切换时的任务现场信息.       X86体系从硬件上支持任务间的切换.为此目的,它增设了一个新段:任务状态段( ...

  8. 对Linux0.11 中 进程0 和 进程1分析

    1. 背景 进程的创建过程无疑是最重要的操作系统处理过程之一,很多书和教材上说的最多的还是一些原理的部分,忽略了很多细节.比如,子进程复制父进程所拥有的资源,或者子进程和父进程共享相同的物理页面,拥有 ...

  9. 搭建Linux0.11系统环境

    学习Linux0.11内核源代码,我们需要搭建一个基于Linux0.11的操作平台:                     1) boch仿真器:可以从http://bochs.sourceforg ...

最新文章

  1. 脑机接口,风口还是入口?
  2. JAVA实现斐波那契数列问题(《剑指offer》)
  3. SQLite大批量插入性能优化
  4. linux删除指定端口的进程
  5. crv仪表上的i是什么指示灯_汽车打不着火是怎么回事,仪表盘汽车发动机故障灯亮是什么情况故障指示灯图解大全集...
  6. 老李分享:持续集成学好jenkins之Git和Maven配置
  7. Rails secret token bug
  8. 花生壳+FileZilla搭建公网FTP服务器
  9. 凯利公式和复利公式,与概率和时间为友
  10. 蓝牙电话之HFP-通话
  11. 串口通信 数据采集软件 上位机 数据采集软件,可以采集plc,串口通信设备,tcp通信设备的数据
  12. python刷网易云_Python脚本用于定时关闭网易云音乐PC客户端
  13. springboot整合分布式任务调度 elastic-job
  14. 计算机jsp外文文献,JSP英文参考文献
  15. VM虚拟机 .vmdk文件,拆分多个文件,合并单个文件
  16. 温控中使用PID控制算法
  17. MATLAB图像的两种模糊模式
  18. 练习-Java字符串之StringToKenizer类分割字符串之计算手机话费总额
  19. oralce启动问题You may need to set ORACLE_HOME to your Oracle software directory
  20. 使用Nginx访问图片报404

热门文章

  1. JavaScript强制类型转换(String)
  2. Centos-虚拟机Centos找不到网络适配器
  3. python 父类调用子类的属性,python父类中调用子类
  4. 使用树结构存储医院楼房结构
  5. 2022-07-08 第七小组 闫馨月 学习笔记
  6. 小米9 从后台回到前台后 Dialog不显示 只有半透明的背景
  7. 三个动物分水果的故事
  8. nova network-vif-plugged事件分析1
  9. 电脑小白自学linux,Linux小小白的学习经历那点事
  10. Spring Cloud H (二)服务注册中心 Zookeeper