Linux内核编程实验报告2.pdf
Linux 内核分析实验报告实验题 目:shell编程实验目的:学习如何编写一个Linux shell程序,使得有机会了解如何创建子进程来执行一项专门的工作以及父进程如何继续子进程的工作硬件环境:内存 1G以上软件环境:Linux(Ubuntu)2-6 实验步骤:一:实验原理简介用户输入一个字符串数组。第一步:shell程序分析出其中的各个参数,将参数分别存储在argv1 和 argv2 字符串数组中(运用编译原理中的自动机实现),并分析其中动作类型标识符(管道,重定向等);第二步:创建子进程,调用系统函数 execvp 函数,运行相应的指令。重定向输出:将标准输出换为指定的文件。close(1)指令关闭,当前进程的标准输出文件。即切断stdout 文件与描述符为1 的文件的关联。然后用open函数打开指定文件,得到文件描述符 file1,调用 dup函数将 1 号文件描述符指向目标输出,file1任务完成,close(file1),使得指向目标文件的文件描述符仅仅是 1 号文件描述符。调用execvp 运行指定程序,执行结果输入到指定文件之中。(见图 2-1)(2-1)重定向输入:同理。管道:申请一个管道,创建两个子进程。子进程 1 将标准输出换为管道的写端,子进程 2 将标准输入换为管道的读端,执行相应的指令,结果输出。(见图 2-2)(图 2-2)后台执行:结尾以&结尾的指令,shell不用等待子进程执行完,因此wait()操作没有必要。在这里,在子进程中又创建了一个子进程(孙子进程),然后把孙子进程的父进程杀掉,如此,孙子就由init进程负责清理,因此,就做到了后台处理得目的。(见图 2-3)(图 2-3)同时处理多条指令:创建两个子进程,分别执行在 argv1 和 argv2 中的参数,得到结果,输出到标准输出屏幕上。(见图 2-4)(图 2-4)二:主要函数介绍 1:系统调用函数(1)int execvp(const char*file,char*const argv);函数说明:execvp()会查找符合参数file 的文件名,找到后便执行该文件,然后将第二个参数argv 传给该欲执行的文件。(2)int dup(int filedes);函数说明:dup 返回新文件描述符是当前可用的为您教案描述符的最小数值。(3)int close(int filedes);函数说明:关闭一个打开的文件,输入参数是文件描述符。(4)int access(const char*pathname,int mode);函数说明:判断文件pathname是否存在2:自定义函数:(1)Char*orderpath(char*name);函数说明:在环境变量的目录中,逐个对name文件名进行配对,如果配对成功返回文件的绝对路径。三:结果检测:(1)管道(正确)(2)重定向输出、此时文件jieguo 中的内容是(正确)(3)同时执行两条指令(正确)(4)后台执行(正确)结论分析与体会:shell是用户程序与系统内核交互的窗口,用户程序通过这样一个程序,可以方便地实现操作系统接口的调用。本次实验中,我的感受是自己一些基本的 shell指令不是很熟悉,但是通过这个实验,加深了对管道,重定向的机制的运用。这对理解Linux 内核是有很大帮助的。附:程序源代码/*myshell.c -description -copyright :(C)2002 by Function :shell,&,|I/O */#include#include#include#include#define LB_SIZE 80#define LS 80 FILE*file1,*file2;char*lineBuf,*tempBuf,*filename;enum fangshiPIPE,ORIENT_input,ORIENT_output,NORMAL,BACK,MUL;char*env=/usr/local/sbin/,/usr/local/bin/,/usr/sbin/,/usr/bin/,/sbin/,/bin/,/usr/games/;char*orderpath(char*name)int i=0;while(i7)strcpy(tempBuf,envi);lineBuf=strcat(tempBuf,name);if(access(lineBuf,0)=0)break;i+;return lineBuf;int main()char*argv110,*argv210;int fd2;int i,j,k,type,canshu_number,canshu_number2;char current;int second;lineBuf=(char*)malloc(LB_SIZE+1);tempBuf=(char*)malloc(LB_SIZE+1);/filename=(char*)malloc(LB_SIZE+1);for(i=0;i)jishu=0;second=1;type=ORIENT_output;else if(tempBufi=)(second=0)?canshu_number+:canshu_number2+;jishu=0;type=ORIENT_input;else if(tempBufi=;)second=1;jishu=0;type=MUL;else if(second=0)argv1canshu_number-1jishu+=tempBufi;else if(second=1)argv2canshu_number2-1jishu+=tempBufi;i+;/printf(字 符 数 是%d 参 数1个 数 是%d 参 数2个 数是%dn,i,canshu_number,canshu_number2);/打印出解析出来的参数/for(i=0;icanshu_number;i+)/printf(参数依次是%sn,argv1i);/for(i=0;icanshu_number2;i+)/printf(第二个参数依次是%sn,argv2i);switch(type)case NORMAL:if(fork()=0)/子进程 filename=orderpath(argv10);argv1canshu_number=NULL;execvp(filename,argv1);exit(0);else/父进程 wait();break;case PIPE:/对于管道的 处理 pipe(fd);if(fork()=0)close(1);/关闭输 出 dup(fd1);/指定管道的 输出为默认的输出 close(fd1);close(fd0);/第一个子 进程负责写文件内容 filename=orderpath(argv10);argv1canshu_number=NULL;execvp(filename,argv1);exit(0);else close(0);dup(fd0);close(fd0);/指定管道的 输入为默认的输 close(fd1);/第二个子 进程负责读 文件内容 filename=orderpath(argv20);argv2canshu_number2=NULL;execvp(filename,argv2);break;case ORIENT_output:if(fork()=0)/子进程 strcpy(tempBuf,argv20);file2=open(tempBuf,O_WRONLY);close(1);dup(file2);close(file2);argv1canshu_number=NULL;filename=orderpath(argv10);execvp(filename,argv1);exit(0);else/父进程 wait();break;case ORIENT_input:printf(ddddddddddddddddddddddn);if(fork()=0)/子进程 strcpy(tempBuf,argv20);file1=open(tempBuf,O_WRONLY);close(0);dup(file1);close(file1);argv1canshu_number=NULL;filename=orderpath(argv10);execvp(filename,argv1);exit(0);else/父进程 wait();break;case MUL:if(fork()=0)printf(*n);filename=orderpath(argv10);argv1canshu_number=NULL;execvp(filename,argv1);printf(*n);exit(1);else printf(*n);filename=orderpath(argv20);argv2canshu_number2=NULL;execvp(filename,argv2);printf(*n);break;case BACK:if(fork()=0)/子进程 if(fork()=0)filename=orderpath(argv10);argv1canshu_number=NULL;execvp(filename,argv1);exit(0);else exit(1);else/父进程 /wait();/printf(%d,getpid();break;return 1;/*END*/