7 I/O设备管理实验
7.1 实验6.1. 观察实验
1、实验目的
掌握与设备管理有关的Linux命令。
2、实验内容
? 用stat命令查看机器上硬盘特别文件的I节点内容
? 在Linux下,查看/proc与内存管理相关的文件,解释显示结果
3、实验结果示例
参见以下截图
7.2 实验6.2 代码分析
阅读 Linux/Minix中以下模块的调用主线(1)print函数内部实现模块调用主线。(2) scan函数内部实现模块调用主线。写出分析报告。
7.3 实验6.3 编程实验
1、实验目的
编写一个daemon进程,该进程定时执行 ps命令,然后将该命令的输出写至文件F1尾部。通过此实验,掌握Linux I/O系统相关内容。
2、实验原理
在这个程序中,首先fork一个子程序,然后,关闭父进程,这样,新生成的子进程被交给init进程接管,并在后台执行。
新生成的子进程里,使用system系统调用,将ps的输出重定向,输入到f1.txt里面。
3、程序源代码清单(参考)
main() { }
int p;
p = fork(); if(p > 0) {
exit(0); }
else if(p == 0) {
for(i = 0; i < 100; i++) { }
sleep(100);
system(\
} else { }
perror(\
7.4 实验6.4 设备驱动程序
1、实验目的
了解Linux的设备驱动程序的组织结构和设备管理机制,编写简单的字符设备和块设备驱动程序。
2、实验内容
a.
编写字符型设备驱动程序,该字符设备包括5个基操作:scull_open()、scull_write()、scull_read、scull_ioctl、scull_release(), 同时还需要编写一个测试程序 b.
编写字符型设备驱动程序,该字符设备包括5个基操作:sbull_open()、sbull_write()、sbull_read、sbull_ioctl、sbull_release()
8. 文件系统管理实验
8.1 实验7.1 代码分析
1、实验目的
了解与文件管理有关的Linux内核模块的代码结构。
2、实验内容
阅读 Linux/Minix中有关文件模块的调用主线,并写出分析报告,包括
? 文件建立模块,即系统调用create() ? 文件删除模块,即系统调用rm() ? 读/写模块,即 read/write
3、分析报告示例
A. 创建文件模块分析
5780 /*creat system call */ 5781 Creat() 5782 {
5783 resister *ip; 5784 extern uchar; 5785
5786 ip = namei(&uchar,1); 5787 if(ip == NULL){ 5788 if(u.u_error) 5789 return;
5790 ip = maknode(u.u_arg[1]&07777&(~ISVTX)); 5791 if (ip == NULL) 5792 return; 5793 open1(ip,FWRITE,2); 5794
}else
5795 open1(ip,FWRITE,1); 5796 }
第5 7 8 6:“namei”( 7 5 1 8 )将一路径名变换成一个“inode”指针。“uchar”是一个过程的名字,它从用户程序数据区一个字符一个字符地取得文件路径名。
5 7 8 7:一个空“inode”指针表示出了一个错,或者并没有具有给定路径名的文件存在。 5 7 8 8:对于出错的各种条件,请见U P M的C R E AT ( I I )。 5 7 9 0:“maknode”( 7 4 5 5 )调用“ialloc”创建一内存“ inode”,然后对其赋初值,并使其进入适当的目录。注意,显式地清除了“粘住”位( I S V T X )。
B. 删除文件rm模块分析
3510 unlink() 3511 {
3512 resister *ip,*pp; 3513 extern uchar; 3514
3515 pp = namei(&uchar,2); 3516 if (pp ==NULL) 3517 return; 3518 prele(pp);
3519 ip = iset(pp ->dev,u.u_dent.u_ino); 3520 if (ip == NULL)
3521 panic (*unlink – iset *);
3522 if ((ip ->i_mode%IFMT) == IFDIR && !suser()) 3523 goto out;
3524 u.u_offset[1] = - DIRSIZ+2; 3525 u.ubase = &u.u_dent; 3526 u.ucount = DIRSIZE +2; 3527 u.u_dent.u_ino = 0; 3528 writei(pp); 3529 ip ->i_nlink--; 3530 ip->i_flag =! IUPD; 3531
3532 out:
3533 iput(pp); 3534 iput(ip); 3535 }
新文件作为永久文件自动进入文件目录。关闭文件不会自动地造成文件被删除。当内存“ inode”项中的“ i _ nlink”字段值为0并且相应文件未被打开时,将删除该文件。在创建文件时,该字段由“ m a k n o d e”赋初值为1。系统调用“ link”( 5 9 4 1 )可将其值加1,系统调用“unlink”( 3 5 2 9 )则可将其值减1。创建临时“工作文件”的程序应当在其终止前执行“ unlink”系统调用将这些文件删除。 注意,“unlink”系统调用本身并没有删除文件。当引用计数( i _ count )被减为0时( 7 3 5 0、7 3 6 2 ),才删除该文件。
为了减少在程序或系统崩溃时遗留下来的临时文件所带来的问题,程序员应当遵守下列约定:
(1) 在打开临时文件后立即对其执行“ unlink”操作。
(2) 应在“tmp”目录下创建临时文件。在文件名中包括进程标识数就可构成一惟一文件名
参考文献:《莱昂氏源代码分析》
北 京 邮 电 大 学
计算机学院
《操作系统》课程实验
Linux 操作系统内核 实 验 指 导 书
2014年9月
目 录
1.实验大纲 .................................................................................................................... 5
1.1 实验目的 ............................................................................................................ 5 1.2实验内容说明 ...................................................................................................... 5
1.2.1 第1组 系统安装实验................................................................................ 5 1.2.2 第2组Linux内核实验 .............................................................................. 6 1.2.3 第3组 进程管理....................................................................................... 6 1.2.4 第4组 存储管理....................................................................................... 7 1.2.5 第5组 进程通信....................................................................................... 7 1.2.6 第6组 I/O设备管理 ................................................................................. 8 1.2.7 第7组 文件系统管理................................................................................ 8
!1.3实验要求 ............................................................................................................ 9 2. 系统安装实验 ............................................................................................................ 10
2.1 实验1.1 Linux系统安装 .................................................................................... 10
1、实验目的 .................................................................................................... 10 2、实验内容(以Red Hat Linux7.2为例) ........................................................ 10 2.2 实验1.2 虚拟机VM软件安装............................................................................11
1、实验目的 .....................................................................................................11 2、实验内容 .....................................................................................................11 2.3 实验1.3 Shell编程 ............................................................................................ 12
1、实验目的与内容 .......................................................................................... 12 2、程序源代码清单(参考) ............................................................................ 12 3. Linux内核实验 ........................................................................................................... 13
3.1 实验2.1 观察Linux行为................................................................................. 13
1、实验目的 .................................................................................................... 13 2、实验内容 .................................................................................................... 13 3、程序源代码清单(参考) ............................................................................ 13 3.2 实验2.2 内核定时器 ....................................................................................... 15
1、实验目的 .................................................................................................... 15
2、实验内容 .................................................................................................... 16 3、程序源代码清单(参考) ............................................................................ 16 3.3 实验2.3内核模块 ............................................................................................. 23
1、实验目的 .................................................................................................... 23
2、实验内容 .................................................................................................... 23 3、实验原理 .................................................................................................... 23 4、实验步骤 .................................................................................................... 23 3.4 实验2.4 系统调用 ............................................................................................ 26
1、实验目的 .................................................................................................... 26 2、实验内容与步骤 .......................................................................................... 26
4 进程管理实验 ............................................................................................................. 28
4.1 实验3.1 进程行为观察 ..................................................................................... 28
1、实验目的 .................................................................................................... 28 2、实验内容 .................................................................................................... 28 4.2 实验3.2 代码分析 ............................................................................................ 28
1、实验目的 .................................................................................................... 28 2、实验内容 .................................................................................................... 28 4.3 实验3.3 Shell编程 ............................................................................................ 28
1、实验目的 .................................................................................................... 28
2、实验内容1.................................................................................................. 28 3、实验内容2.................................................................................................. 30
5. 存储管理实验 ............................................................................................................ 33
5.1 实验4.1 观察实验 ............................................................................................ 33
1、实验目的 .................................................................................................... 33 2、实验内容 .................................................................................................... 33 5.2 实验4.2 存储管理代码分析 .............................................................................. 33
1、实验目的 .................................................................................................... 33 2、实验内容 .................................................................................................... 33 3、示例—缺页中断处理程序分析 ..................................................................... 33 5.3 实验4.3虚拟存储器管理 ................................................................................... 35
1、实验目的 .................................................................................................... 35
2、实验内容 .................................................................................................... 35 3、实验原理 .................................................................................................... 36
4、试验步骤 .................................................................................................... 36 5、源程序代码清单(参考) ............................................................................ 37
6. 进程通信 ................................................................................................................... 39
6.1 实验5.1 观察实验 ............................................................................................ 39
1、实验目的与内容 .......................................................................................... 39 2、实验原理 .................................................................................................... 39 6.2 实验5.2 代码分析 ............................................................................................ 39
1、实验目的 .................................................................................................... 39 2、实验内容 .................................................................................................... 40 3、实验结果示例 ............................................................................................. 40 6.3 实验5.3 进程同步实验 ..................................................................................... 42
1、实验目的 .................................................................................................... 42 2、实验内容 .................................................................................................... 42 3、实验原理 .................................................................................................... 42 4、实验步骤及部分代码清单(参考) .............................................................. 43
7 I/O设备管理实验 ...................................................................................................... 46
7.1 实验6.1. 观察实验............................................................................................ 46
1、实验目的 .................................................................................................... 46
2、实验内容 .................................................................................................... 46 3、实验结果示例 ............................................................................................. 46 7.2 实验6.2 代码分析 ............................................................................................ 47 7.3 实验6.3 编程实验 ............................................................................................ 47
1、实验目的 .................................................................................................... 47
2、实验原理 .................................................................................................... 47 3、程序源代码清单(参考) ............................................................................ 47 7.4 实验6.4 设备驱动程序 ..................................................................................... 48
1、实验目的 .................................................................................................... 48 2、实验内容 .................................................................................................... 48 8. 文件系统管理实验 ..................................................................................................... 49
8.1 实验7.1 代码分析 ............................................................................................ 49
1、实验目的 .................................................................................................... 49 2、实验内容 .................................................................................................... 49 3、分析报告示例 ............................................................................................. 49 8.2 实验7.2 编程实验1 .......................................................................................... 51
1、实验目的与内容 .......................................................................................... 51 2、程序源代码清单(参考) ............................................................................ 51 8.3 实验7.3 编程实验2 .......................................................................................... 52
1、实验目的与内容 .......................................................................................... 52 2、程序源代码清单(参考) ............................................................................ 53
1.实验大纲
1.1 实验目的
在学习《操作系统》课程内容同时,以开放式源代码操作系统Linux为实验平台,同步完成Linux操作系统内核的代码分析和修改等7组基本课程实验。通过实验,熟悉Linux系统使用方法,掌握Linux内核系统结构,了解Linux进程管理、存储管理、设备管理、文件系统等资源管理功能的实现机理和典型算法。初步掌握运用内核开发环境对内核进行修改完善的能力。
通过本课程实验,使得学生熟悉Linux操作系统相关技术,并进一步巩固
课堂所学有关操作系统人机界面和资源管理得相关知识;并通过Linux源代码分析和简单编程,培养学生对实际操作系统的基本系统分析能力。
1.2实验内容说明
Linux基本实验由以下7组实验组成。
1.2.1 第1组 系统安装实验
实验1.1 Linux系统安装
从CD-ROM安装Red Hat Linux操作系统,如Red Hat Linux7.2,建立后续各个实验的运行环境。 实验1.2 虚拟机安装
在配备Windows操作系统Host机上,安装虚拟机软件Virtual PC for
Windows或VMware For Windows,进行BIOS设定, 对硬盘进行分区和格式化,安装Linux操作系统,以便在一台机器上模拟出多种操作系统运行环境。 实验1.3 Shell编程
编制简单的Shell程序,该程序在用户登录时自动执行,显示某些提示信息,
如“Welcome to Linux”, 并在命令提示符中包含当前时间、当前目录和当前用户名等基本信息。
#include
int pfd[2];
char send_buf[100], recv_buf[100]; pipe (pfd); pid = fork (); if (pid == 0) { } else {
pid = fork (); if (pid == 0) { close (pfd[0]); } else {
read (pfd[0], recv_buf, sizeof(recv_buf)); printf (\
read (pfd[0], recv_buf, sizeof(recv_buf)); printf (\wait (0); wait (0); close (pfd[0]);
strncpy (send_buf, \lockf (pfd[1], F_LOCK, 0);
write (pfd[1], send_buf, strlen(send_buf)); sleep (1);
lockf (pfd[1], F_ULOCK, 0); close (pfd[1]); close (pfd[0]);
strncpy (send_buf, \lockf (pfd[1], F_LOCK, 0);
write (pfd[1], send_buf, strlen(send_buf)); sleep (1);
lockf (pfd[1], F_ULOCK, 0); close (pfd[1]);
} }
return 0;
}
pipe的调用主线:
pipe (pfd);pid = fork (); 如果pid == 0,则调用:
close (pfd[0]);strncpy ();lockf ();write ();sleep ();lockf ();函数,通过进程向管道中写入数据, 如果调用不成功,调用了close (pfd[0]);strncpy ();lockf ();write ();sleep ();lockf ();函数,创建一个进程,如果成功,通过该进程向管道中写入数据;如果不成功,则从管道中读出数据。
6.3 实验5.3 进程同步实验
1、实验目的
深入学习Linux内核,在学习linux内核的同步机制的同时,深入分析各种同步机制的实现方案,在此基础上设计和编写一套同步原语。
2、实验内容
设计并实现一个新的同步原语,该原语允许多个进程因一个事件而阻塞,直到其他进程产生这个信号为止。当一个进程产生一个事件的信号时,所有因这个事件而阻塞的进程都取消阻塞。如果信号产生时,没有进程因为这个信号而阻塞,那么这个信号无效。
实现下列系统调用:
int evntopen(int); int evntclose(int);
int evntwait(int evenNum); void evntsig(int evenNum);
3、实验原理
在深入学习软中断信号,信号量和管道的工作原理和实现机制后,我们知道,一个事件必须有一个事件号,一系列的进程等待这个事件发生,那么肯定需要一个等待队列,所以睡眠的进程就放到这个队列中去。通过考察linux中如wake_up、sleep_on等的实现我们将构建上述同步原语。
首先建立一个存放事件的队列,通过简单的链表即可实现。 //定义结构,保存事件队列 typedef struct __eventStruct{ int eventNum;
wait_queue_head_t *p;
struct __eventStruct *next; } __eventNode;
//两个全局变量记录链表的头尾
__eventNode *lpmyevent_head = NULL; //指向链表头 __eventNode *lpmyevent_end = NULL; //指向链表尾
4、实验步骤及部分代码清单(参考)
(1)实现函数定义
定义Open同步原语,当Open一个事件的时候,有两种情况:一是事件已经存在,只需要返回Event事件号即可,第二种是事件链表中没有该事件,简单的处理办法直
接返回-1,表示事件不存在。当传递参数0 的时候,将产生一个新事件。 int eventopen(int eventNum) {
__eventNode *newNode; __eventNode *prevNode; if(eventNum)
if(!scheventNum,&prev)) return -1; else return eventNum; else {
newNode = (__eventNode *)kmalloc(
sizeof(__eventNode), GFP_KERNEL); newNode->p =(wait_queue_head_t *)kmalloc(
sizeof(wait_queue_head_t));
newNode->next = NULL;
newNode->p->task_list.next = &newNode->p->task_list; newNode->p->task_list_prev =
&newNode->p->task_list;
if(!lpmyevent_head)
{
newNode->eventNum =2;
lpmyevent_head =lpmyevent_end =newNode; return newNode->eventNum; } else {
newNode->eventNum = lpmyevent_end->eventNum + 2; lpmyevent_end->next = newNode; lpmyevent_end = newNode; }
return newNode->eventNum; } return 0;
}
定义evntsig(eventNum),evntsig()要完成的功能是唤醒所有等待该事件发生的进程。我们只需要在事件列表上找到该事件,然后调用wake_up()。
int evntsig(int eventNum) {
__eventNode *tmp = NULL; __eventNode *prev = NULL;
if(!(tmp = scheventNum(eventNum,&prev)) return;
wake_up(tmp->p); return 1; }
evntwait()将一个进程加到他要等待的事件队列中去。
int evntwait(int eventNum) {
__eventNode *tmp; __eventNode *prev = NULL; wait_queue_t wait;
unsigned long flags;
if(tmp =scheventNum(eventNum,&prev)) {
wait.task = current;
current->state = TASK_UNINTERRUPTIBLE; write_lock_irqsave(&temp->p->lock,flags); __add_wait_queue(tmp->p,&wait); write_unlock(&tmp->p-lock);
schedule();
write_lock_irq(&tmp->p->lock);
__remove_wait_queue(tmp->p,&wait); write_unlock_irqrestore(&tmp->p->lock,flags); }
}
至于evntclose()先在事件队列中找到该事件,然后根据事件在该链表中的位置进行特定的处理,之后唤醒所有睡眠在该事件上的事件,最后将这个事件从链表中删除,释放内存。
int evntclose(int eventNum) {
__eventNode *prev; __eventNode *releaseItem;
evntsig(eventNum);
if(releaseItem = scheventNum(eventNum,&prev)) {
if (releaseItem == lpmyevent_end)
lpmyevent_end = prev; if (releaseItem == lpmyevent_head) {
lpmyevent_head = lpmyevent_head->next; goto wake; }
prev->next = releadeItem->next; } wake:
if(releaseItem) {
kfree(releaseItem); return 1; } return 0;
} 最后是一个辅助调度函数scheventNum()函数。他有两个参数eventNum和prev,前者是事件号,后者是要返回的一个 __eventNode类型的指向指针的指针,它将指向要要寻找节点的上一节点。函数返回要寻找的事件节点。 __eventNode * scheventNum(int eventNum,__eventNode **prev) {
__eventNode *tmp = lpmyevent_head; *prev = NULL; while(tmp)
{
if(tmp->eventNum == eventNum) return tmp; *prev = tmp; tmp =tmp->next; }
return NULLL; }
(2)同步原语实现的函数转化为系统调用,修改系统初始化代码,编译内核。
通过fork()创建子进程,用execvp()更改子进程代码,用wait()等待子进程结束。
这三个系统调用可以很好地创建多进程。另一方面,编写的Shell要实现管道功能,需要用pipe(创建管道使子进程进行通信。 说明:
? 本程序允许同时有重定向和管道,也可以不带它们,但是管道数目不得超过一个
? 重定向的位置应该是在最后
? 设有一个内部命令exit用来退出Shell (2)源代码清单(参考)
#include
int hd;
char buf[256];
char *buf2,*buf3,*cmd,*cmd2,*cmd3,*argv[64],*argv2[64],*argv3[64]; int n,sv,fd[2]; for(;;) {
printf(\
if(fgets(buf,sizeof(buf),stdin)==NULL) exit(0); buf2=strstr(buf,\ buf3=strstr(buf, \ if (buf2)
*buf2++='\\0'; if(buf3)
*buf3++='\\0';
cmd=strtok(buf,\ if (cmd) {
if (strcmp(cmd,\ n=0;
argv[n++]=cmd;
while(argv[n++]=strtok(NULL,\ else exit(1); if (buf2){
cmd2=strtok(buf2,\ n=0;
argv2[n++]=cmd2;
while(argv2[n++]=strtok(NULL,\ if (buf3){
cmd3=strtok(buf3,\ n=0;
argv3[n++]=cmd3;
while(argv3[n++]=strtok(NULL,\
if (!cmd2){
if (fork() == 0) { execvp(cmd,argv);
fprintf(stderr,\ %s\\n\ exit(1);} wait(&sv); } else {
} } }
pipe(fd); if(fork()==0) { hd=-1;
dup2(fd[0],0);
if (cmd3) hd=open(cmd3, O_CREAT|O_WRONLY,0666); if (hd != -1 ) dup2(hd,1); close(fd[0]); close(fd[1]); close(hd);
execvp(cmd2,argv2);
fprintf(stderr,\ ******ERROR******: %s\\n\ } else if(fork()==0) { dup2(fd[1],1); close(fd[0]); close(fd[1]);
execvp(cmd,argv);
fprintf(stderr,\ ******ERROR******: %s\\n\ }
close(fd[0]); close(fd[1]); wait(&sv); wait(&sv);
5. 存储管理实验
5.1 实验4.1 观察实验
1、实验目的
利用Linux相关程序和命令,观察程序结构和进程执行情况。
2、实验内容
1. 在Linux下,使用gdb程序观察一个程序文件的内容和结构。启动该程序执行,再用GDB观察其内存映象的内容和结构。
2. 在Linux下,用free 和vmstat命令观察内存使用情况。
3. 在Linux下,查看/proc与内存管理相关的文件,并解释显示结果。
5.2 实验4.2 存储管理代码分析
1、实验目的
了解Linux内核中存储管理部分的代码结构和主要功能。
2、实验内容
阅读 Linux/Minix中以下模块的调用主线,并写出分析报告
? exec系统调用的内部实现模块调用主线 ? malloc函数的内部实现模块调用主线 ? 缺页中断处理程序
3、示例—缺页中断处理程序分析
当程序在运行中,访问到的无效的虚拟地址的时候,系统将激发出缺页中断。激发缺页中断的情况通常有四种:
1. C-O-W型中断,当某个进程进行写操作时,如果写的页是多进程在使用时,为了不影响其它进程的正常运行,通常需要将该页复制一份,供执行写操作的进程单独使用。
2. 被访问的物理页由于太长时间没有访问而被kswapd置换到swap file中。 3. 被访问的物理页由于是第一次访问,所以还在磁盘上或由于访问后被置换时
因为没有发生写操作,而未写到swap file中。
4. 当进程动态的访问一片存储区域时,如在程序中动态开辟的数组等,则该页
不在swap file中,也不在磁盘上。
缺页中断服务入口程序是函数do_page_fault。do_page_fault首先进行各种错误情况判断,并作相应处理。然后根据error_code 来判断缺页中断类型: (1) 第一种情况采用do_wp_page函数来处理
(2) 第二、三、四种情况由do_no_page函数来处理。
下面将分别介绍这些函数的流程图。
void do_wp_page(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long address, int write_access)
为复制可写页申请一页空间异常根据address计算pgd ,pmd,pte退出=1使用该物理页的进程>1 ?>1将物理页复制到复制页上将该物理页置\将复制页链入虚存中释放原先分配的复制页将指向原先物理页的pte释放掉退出
图1 do_wp_page示意图
void do_no_page(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long address, int write_access) {
根据address计算三级页表中pgd/pmd/pte的值,如无对应的项,分配空间将
其填上
if ( pte_present(entry) )
该页已在内存中,return;
//可能是共享该页的其他进程已将该页读入
else if (!pte_none(entry)) //情况2 pte中该项非空,说明该页被kswapd置换到swap file中,
调用 do_swap_page读入该页;
else if ( !vma->vm_ops || !vma->vm_ops->nopage) //情况4 该页对应的VMA块没有相应的nopage操作,说明该VMA块对应的是数据段内容
}
调用__get_free_page操作为该页分配内存,并将该页赋值为0,同时链入
该进程的页表中
else //情况3 调用虚拟块操作将磁盘中对应文件读入page中,
将pte表中对应的项指向该页。
将该页dirty位置位,如果该页有多进程使用,且非共享,置写保护位。
根据address计算三级页表中pgd/pmd/pte的值,如无对应的项,分配空间将其填上在空(2)该页在内存中?不在该页非空?不在(4)退出调用vma->vm->ops->swapin在(3)该页有无no_page操作调用__get_free_page重新分配内存,将该page赋值为0,同时链入tsk的页表中调用虚拟块操作将磁盘中对应的文件读入page中将page置”dirty”,如果该页有多进程使用,且非共享,置写保护位退出将page的entry链入tsk的页表图 2 do_no_page示意图( 2、3、4分别代表2、3、4种情况)
参考文献:《莱昂氏源代码分析》
5.3 实验4.3虚拟存储器管理
1、实验目的
学习Linux虚拟存储实现机制;编写代码,测试虚拟存储系统的缺页错误(缺页中断)发生频率。
2、实验内容
修改存储管理软件以便可以判断特定进程或者整个系统产生的缺页情况,达到一下目标 ? 预置缺页频率参数 ? 报告当前缺页频率
3、实验原理
由于每发生一次缺页都要进入缺页中断服务函数do_page_fault一次,所以可以认为执行函数的次数就是系统发生缺页的次数。因此可以定义一个全局的变量pfcount作为计数变量,在执行do_page_fault时,该变量加1。系统经历的时间可以利用原有系统的变量jiffies,这是一个系统计时器。在内核加载以后开始计时,以10ms为计时单位
实现施可采用2种方案
(1) 通过提供一个系统调用来访问内核变量pfcount和jiffies。但是增加系统变量存在居
多的不便,如重新编译内核等,而且容易出错以致系统崩溃。 (2) 通过/proc文件系统以模块的方式提供内核变量的访问接口。在/proc文件系统下建立
目录pf以及在该目录下的文件pfcount和jiffies。
4、试验步骤
(1)提供系统变量pfcount并编译内核
声明变量pfcount
文件linux/include/linux/mm.h
增加声明
extern unsigned long volatile pfcount;
定义变量
文件linux/arch/i386/mm/fault.c 定义变量
unsigned long volatile pfcount;
变量操作
文件linux/arch/i386/mm/fault.c
增加自增操作
在do_page_fault系统调用的全局范围内增加操作 pfcount++;
同时在/kernel/ksyms.c中export变量 增加
EXPORT_SYMBOL(pfcount); EXPORT_SYMBOL(jiffies);
之后编译内核
(2)提供一个读取模块文件pf.c,在proc中添加访问接口
至于如何添加和编译模块就不再仔细说明,在第四个试验中我们就通过考擦proc伪文件系统学习linux独特的模块机制。用命令
gcc –D__KERNEL__ -c pf.c –o pf.o –I/user/src/linux/include生成文件pf.o,院后执行
insmod pf.o加载模块。这样通过/proc文件系统接口我们就可以轻松的读取我们所需要的两个变量数据了。使用命令
cat /proc/pf/pfcount /proc/pf/jiffies就可以在终端中打印出系统至今为止的缺页次数和进
来的jiffies数目了。
5、源程序代码清单(参考)
#define MODULE #include
struct proc_dir_entry *proc_pf;
struct proc_dir_entry *proc_pfcount, *proc_jiffies;
extern unsigned long jiffies, pfcount;
static inline struct proc_dir_entry *proc_pf_create(
const char* name, mode_t mode,
get_info_t *get_info)
return create_proc_info_entry(
name, mode,
proc_pf, get_info);
}
int get_pfcount(char *buffer, char **start, off_f offset, int length) {
int length =0;
length = sprintf(buffer, \ return length; }
int get_jiffies(char *buffer, char **start, off_f offset, int length) {
int length =0;
length = sprintf(buffer, \ return length;
}
int init_module(void) {
proc_pf =proc_mkdir(\
proc_pf_create(\ proc_pf_create(\ return 0; }
void cleanup_module(void)
{
remove_proc_entry(\ remove_proc_entry(\ remove_proc_entry(\
6. 进程通信
6.1 实验5.1 观察实验
1、实验目的与内容
在Linux下,用ipcs()命令观察进程通信情况,了解Linux基本通信机制。
2、实验原理
Linux IPC继承了Unix System V及DSD等,共有6种机制: 信号(signal)、管道(pipe和命名管道(named piped)、消息队列(message queues)、共享内存(shared memory segments)、信号量(semaphore)、套接字(socket)。 本实验中用到的几种进程间通信方式:
(1)共享内存段(shared memory segments)方式
– 将2个进程的虚拟地址映射到同一内存物理地址,实现内存共享
– 对共享内存的访问同步需由用户进程自身或其它IPC机制实现(如信号量) – 用户空间内实现,访问速度最快。
– Linux利用shmid_ds结构描述所有的共享内存对象。 (2)信号量(semaphore)方式
– 实现进程间的同步与互斥 – P/V操作, Signal/wait操作
– Linux利用semid_ds结构表示IPC信号量 (3)消息队列(message queues)方式
– 消息组成的链表,进程可从中读写消息。 – Linux维护消息队列向量表msgque,向量表中的每个元素都有一个指向msqid_ds结
构的指针,每个msqid_ds结构完整描述一个消息队列
LINUX系统提供的IPC函数有: ? msgget(关键字,方式):创建或打开一个消息队列
? msgsnd(消息队列标志符,消息体指针,消息体大小,消息类型): 向队列传递消息 ? msgrcv(消息队列标志符,消息体指针,消息体大小,消息类型): 从队列中取消息
? msgctl(消息队列标志符,获取/设置/删除,maqid_ds缓冲区指针): 获取或设置某
个队列信息,或删除某消息队列
Linux系统中,内核,I/O任务,服务器进程和用户进程之间采用消息队列方式,许多微内核OS中,内核和各组件间的基本通信也采用消息队列方式.
6.2 实验5.2 代码分析
1、实验目的
通过分析Linux中相关模块调用主线的代码结构,了解模块调用机制。
2、实验内容
阅读 Linux/Minix中以下模块的调用主线,并写出分析报告
? kill系统调用内部实现模块调用主线 ? pipe系统调用内部实现模块调用主线
3、实验结果示例
进程的创建: #include
pid_t pid; pid = fork (); if (pid == 0) { }
printf (\pid = fork (); if (pid == 0) {
printf (\
} else {
} else { printf (\}
return 0;
kill命令调用主线:
先向Linux系统的内核发送一个系统操作信号和某个程序的进程标识号,然后系统内核就可以对进程标识号指定的进程进行操作。比如在top命令中,我们看到系统运行许多进程,有时就需要使用kill中止某些进程来提高系统资源。在讲解安装和登陆命令时,系统多个虚拟控制台的作用是当一个程序出错造成系统死锁时,可以切换到其它虚拟控制台工作关闭这个程序。
管道间通信: #include