急啊!!!
有关的是linux有关知识的报告。
谢谢
急啊!!!
有关的是linux有关知识的报告。
谢谢
楼主你好
一份《深入分析linux内核源码》已发至楼主QQ邮箱。
请注意查收,谢谢。
(一) Linux编程环境的熟悉 实验要求: 1、 编写一个C程序,其内容为实现文件拷贝的功能。 2、 编写一个C程序,其内容分窗口同时显示三个并发进程的运行结果。要求用到linux下的图形库。 程序清单 1、文件拷贝功能: //copy.c #i nclude<fcntl.h> #i nclude<sys/stat.h>
#define NEWFILE (O_WRONLY | O_CREAT | O_TRUNC) //定义新目标文件的打开方式 #define MODE600 (S_IRUSR | S_IWUSR | S_IXUSR) //定义目标文件的使用权限:rwx #define size 1 //定义缓冲区的大小
void filecopy(char * infile,char * outfile) { char buf[size]; int infd,outfd,count; if((infd=open(infile,O_RDONLY))==-1) //以只读方式打开源文件 printf("Opening infile failed!\n"); if((outfd=open(outfile,NEWFILE,MODE600))==-1) //打开目标文件或创建目标文件 printf("Opening outfile failed!\n");
while((count=read(infd,buf,sizeof(buf)))>0) //读文件到缓冲区 if(write(outfd,buf,count)!=count) //写文件到目标文件中 printf("Writing data failed!\n");
if(count==-1) printf("Reading data failed!\n"); close(infd); //关闭文件 close(outfd); }
int main(int argc,char * argv[]) { filecopy(argv[1],argv[2]); //以命令行的形式调用新文件拷贝命令 }
2、 窗口显示三个进程并发执行: //procc.c #i nclude<unistd.h> #i nclude<sys/types.h> #i nclude<curses.h>
int main(void) { int i,j,k,m=0,n=0,l=0; pid_t pid1,pid2; WINDOW * win1,*win2,*win3; initscr(); //屏幕初始化
win1=newwin(5,74,2,2); //创建窗口1 box(win1,ACS_VLINE,ACS_HLINE); for(j=0;j<50;j++) { mvwprintw(win1,2,(5+j),"%s","="); } touchwin(win1); //刷新窗口 w***(win1);
win2=newwin(5,74,9,2); //创建窗口2 box(win2,ACS_VLINE,ACS_HLINE); for(j=0;j<50;j++) { mvwprintw(win2,2,(5+j),"%s","="); } touchwin(win2); //刷新窗口 w***(win2);
win3=newwin(5,74,16,2); //创建窗口3 box(win3,ACS_VLINE,ACS_HLINE); for(j=0;j<50;j++) { mvwprintw(win3,2,(5+j),"%s","="); } touchwin(win3); //刷新窗口 w***(win3);
pid1=fork(); //第一次创建子进程 if(pid1==0) { for(i=0;i<50;i++) { m+=2; mvwprintw(win2,1,20,"%s","child process 1 running..."); mvwprintw(win2,2,(5+i),"%s",">"); //输出进程的运行信息 mvwprintw(win2,2,65,"%d",m); mvwprintw(win2,2,68,"%s","%"); touchwin(win2); //刷新窗口和屏幕 w***(win2); ***(); sleep(1); } mvwprintw(win2,3,20,"%s","process ended");//进程结束信息 touchwin(win2); //刷新窗口和屏幕 w***(win2); ***(); } else { pid2=fork(); //第二次创建子进程 if(pid2==0) { for(j=0;j<50;j++) { n+=2; mvwprintw(win3,1,20,"%s","child process 2 running..."); mvwprintw(win3,2,(5+j),"%s",">"); //输出进程的运行信息 mvwprintw(win3,2,65,"%d",n); mvwprintw(win3,2,68,"%s","%"); touchwin(win3); //刷新窗口和屏幕 w***(win3); ***(); sleep(1); } mvwprintw(win3,3,20,"%s","process ended");//进程结束信息 touchwin(win3); //刷新窗口和屏幕 w***(win3); ***(); } else { for(k=0;k<50;k++) { l+=2; mvwprintw(win1,1,20,"%s","parent process running..."); mvwprintw(win1,2,(5+k),"%s",">"); //输出进程的运行信息 mvwprintw(win1,2,65,"%d",l); mvwprintw(win1,2,68,"%s","%"); touchwin(win1); //刷新窗口和屏幕 w***(win1); ***(); sleep(1); } mvwprintw(win1,3,20,"%s","process ended");//进程结束信息 touchwin(win1); //刷新窗口和屏幕 w***(win1); ***(); sleep(5); endwin(); //退出窗口状态 exit(0); //由父进程来做扫尾工作 } } }
调试过程: 1、 文件拷贝 这个程序是比较简单的,只需要用到几个有关文件系统的系统调用函数。编译和运行也比较顺利。主要是目标文件创建的权限类型要注意,linux自带的拷贝命令创建的目标文件只具备——读-写——的用户权限,但是我这个拷贝命令具有——读-写-执行——三种权限。这个权限可以自己随需要定义。
2、 窗口显示进程 这里我用的是屏幕开发库curses,这里始终要注意的一点是,每次往逻辑屏幕(或窗口)上输出文字的时候,都要刷新物理屏幕(或窗口),以实现程序中的输出和屏幕的实际输出一致。用touchwin(),w***()和***()函数实现刷新。 我受Windows2000启动界面的启发,也将三个进程运行过程的显示做成那样。下面是程序运行效果: (二) 了解linux系统内核代码结构 linux系统内核代码目录结构如下: /usr/src/linux-2.4.18-14—|——abi/ |——arch/ |——configs/ |——crypto/ |——Documentation/ |——drivers/ |——fs/ (包含文件系统的源代码) |——include/ |——init/ |——ipc/ (包含进程通信的源代码) |——kernel/ (包含系统服务功能的源代码) |——lib/ |——mm/ (内存管理源代码) |——net/ +——scripts/ 根目录下四个比较重要的子目录: 1、/dev 该目录包含了连接到该系统设备的文件系统的索引文件,这些文件对于系统完成正常的功能是不可或缺的。 2、/etc 该目录用于存放程序所需的系统配置文件。在该目录下包含了许多重要的文件,如: passwd (passwd以及shadow用于系统保留被授权用户的信息。passwd中保留了有关shadow 用户的所有信息,经过加密以后的口令则被存放于passwd文件中。) fstab (该文件包括用以通知如何安装设备的一系列信息。) host profile (该文件为使用bash、ksh等的用户提供了缺省的初始化文件,用于设置PATH,PSI之类的变量以及缺省的umbask) service (该文件包含一个运行于系统之上的所有服务程序的列表) motd (用于存放当日信息,包括软件升级的时间等等,仅提供给系统管理员) lilo.conf (该文件为lilo引导工具的启动配置文件) 在/etc目录下的两个重要的子目录是 /etc |——X11 该目录存放了诸如XF86Config之类的X server的配置文件 以及各种窗口管理程序大多数的窗口管理软件将对应的配置文件放在X11下的子目录中) +——rc.d(该目录保存了Linux装如以及关闭时运行的初始化脚本) 3、/lib 该目录包含了执行/bin以及/sbin中二进制文件所必须的库文件。几乎所有的应用程序在执行的时候都会用到这个库) 4、/proc 该文件夹包含了Linux提供的一个虚拟文件系统,用于与内核交换信息。由系统在系统启动时产生,通过这些文件能够直接获得系统信息。 usr子目录的重要子树结构: /usr (存放了用户的应用程序以及相关文件。) |——bin (用于存放可执行文件) |——dict |——doc (用于保留文档文件,初学者应当仔细阅读) |——etc (包括了c语言的头文件、GNU的介绍) |——games |——include |——kerberos |——lib (保存了库文件) |——libexec |——local(用来为普通用户或者超级用户安装文件所用和/usr目录在 结构上很相似,设置的目的上也很相似)有如下子目录: |——bin |——doc |——etc |——games |——include |——info |——lib |——man |——sbin +——src |——man |——sbin(用于存放用于系统管理的可执行文件 (不包括不在/sbin下的文件)) |——share |——src (用于存放源代码) |——temp +——x11r6(为xwindows系统所准备,) (三) 分析Linux系统的内核代码和进程调度方法
Y BUG()
N
default case TASK_INTERRUPTIBLE 可中断的等待状态或僵死状态 进程可被信号中断
case TASK_RUNNING 可运行状态 Y
N
Y
(四) 增加系统调用mycall()以及P、V操作 1、在/usr/src/linux-2.4.18-14/kernel/sys.c的最后添加如下代码:
int sys_filecopy(char * infile,char * outfile) { int infd,outfd,count; char buf[256]; mm_segment_t fs; //堆栈保护 fs=get_fs(); set_fs(get_ds());
if((infd=sys_open(infile,O_RDONLY,0))== -1) return(-2); if((outfd=sys_open(outfile,O_WRONLY | O_CREAT,S_IRUSR | S_IWUSR))== -1) return(-3);
while((count=sys_read(infd,buf,256))>0) if(sys_write(outfd,buf,count)!=count) return(-5); if(count==-1) return(-4); sys_close(infd); sys_close(outfd); return(0); set_fs(fs); } int sys_p_sem(int sem_id) { struct sembuf sem_buf; mm_segment_t fs; //堆栈保护 fs=get_fs(); set_fs(get_ds()); sem_buf.sem_num=0; sem_buf.sem_op=-1; sem_buf.sem_flg=SEM_UNDO; if(sys_semop(sem_id,&sem_buf,1)==-1) { printk("P(sem) Failed!\n"); return(0); } set_fs(fs); return(1); }
int sys_v_sem(int sem_id) { struct sembuf sem_buf; mm_segment_t fs; //堆栈保护 fs=get_fs(); set_fs(get_ds());
sem_buf.sem_num=0; sem_buf.sem_op=1; sem_buf.sem_flg=SEM_UNDO; if(sys_semop(sem_id,&sem_buf,1)==-1) { printk("V(sem) Failed!\n"); return(0); } set_fs(fs); return(1); }