已阅读5页,还剩46页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
目 录课程设计任务书3课设内容与过程5一、掌握Linux系统5二、掌握系统调用的实现过程7三、掌握增加设备驱动的方法10四、掌握和了解/proc11课设心得17课程设计任务书19一、掌握Linux系统源程序19二、系统调用的实现过程源程序22三、增加设备驱动的源程序24四、任务管理器源程序27课程设计任务书一、 课设目的1. 掌握Linux操作系统的使用方法;2. 了解Linux系统内核代码结构3. 掌握实例操作系统的实现方法。二、 课设内容1. 掌握Linux操作系统的使用方法,包括键盘命令、系统调用;掌握在Linux下的编程环境。(一) 编一个C程序,其内容为实现文件拷贝的功能;(二) 编一个C程序,其内容为分窗口同时显示三个并发进程的运行结果。要求用到Linux下的图形库。2. 掌握系统调用的实现过程,通过编译内核方法,增加一个新的系统调用。另编写一个应用程序,调用新增加的系统调用(实现的功能为文件拷贝)。3. 掌握增加设备驱动程序的方法。通过模块方法,增加一个新的设备驱动程序,其功能可以简单(实现字符设备的驱动)。4. 了解和掌握/proc文件系统的特点和使用方法 (选做)(一) 了解/proc文件的特点和使用方法;(二) 监控系统状态,显示系统中若干部件使用情况;(三) 用图形界面实现系统监控状态。5. 设计并实现一个模拟的文件系统(选做)多用户的多级目录的文件系统设计。多用户、多级目录、login (用户登录)、系统初始化(建文件卷、提供登录模块)、文件的创建、文件的打开、文件的读、文件的写、文件关闭、删除文件、创建目录(建立子目录)、改变当前目录、列出文件目录、退出。三、 课设说明Linux系统版:Fedora 5.0 6.0ubuntu 10.04 11.10内核版本linux-2.6.x , 尽量使用2.6.32以前的内核版本。四、 考核要求1) 必须独立完成课程设计内容,不分小组,不能有相同的拷贝;2) 上机考试:学生根据老师提出的要求,演示所完成的系统;并回答老师的问题;第4周周四:上午1班 、下午2班 周五上午:3班、 下午4班3) 评分方法:完成1、2题,得50-55分;完成1、2、3题,得55-65分;完成1、2、3、4(5)题,得70-90分;报告:10分。4) 上交:课程设计报告(打印/电子档),内容包括调试记录和程序清单(附注释)。第六周前以班为单位交应用系办公室罗老师处。五、 参考资料i. Linux的“man”帮助ii. Linux内核2.4版源代码分析大全iii. Linux内核源代码分析iv. Linux编程白皮书v. 参考网站:课设内容与过程一、 掌握Linux操作系统的使用方法,包括键盘命令、系统调用;掌握在Linux下的编程环境。(一) 编一个C程序,其内容为实现文件拷贝的功能.a) 任务分析在Linux下面,如果要编译一个C语言源程序,我们要使用GNU的gcc编译器。gcc编译器有许多选项,一般来说我们只要知道其中的几个就够了. -o选项我们已经知道了,表示我们要求输出的可执行文件名. -c选项表示我们只要求编译器输出目标代码,而不必要输出可执行文件. -g选项表示我们要求编译器在编译的时候提供我们以后对程序 进行调试的信息. 知道了这三个选项,我们就可以编译我们自己所写的简单的源程序了,如果想要知道更多的选项,可以查看gcc的帮助文档(可以用man gcc来查看),那里有着许多对其它选项的详细说明。文件拷贝的C程序主要用到如下几个函数:open:打开文件close:关闭文件read:读操作write:写操作open函数有两个形式.如下:int open(const char *pathname,int flags); int open(const char *pathname,int flags,mode_t mode);其中pathname是我们要打开的文件名(包含路径名称,缺省是认为在 当前路径下面).flags可以去下面的一个值或者是几个值的组合. 组合使用时候用竖线“|”隔开。O_RDONLY:以只读的方式打开文件. O_WRONLY:以只写的方式打开文件. O_RDWR:以读写的方式打开文件. O_APPEND:以追加的方式打开文件. O_CREAT:创建一个文件. /创建一个不存在的文件。O_EXEC:如果使用了O_CREAT而且文件已经存在,就会发生一个错误. O_NOBLOCK:以非阻塞的方式打开一个文件. O_TRUNC:如果文件已经存在,则删除文件的内容. 前面三个标志只能使用任意的一个.如果使用了O_CREATE标志,那么我们要使用open的第二种形式.还要指定mode标志,用来表示文件的访问权限.b) 程序源代码见实现文件拷贝的源程序c) 程序运行结果源程序通过编译后会生成可执行文件mycopy,执行mycopy之前,/usr目录下的文件a.txt内容见图 1,文件b.txt内容见图 2。图 1 执行mycopy前a.txt的内容图 2执行mycopy前b.txt的内容执行mycopy后,目录/usr下文件b.txt内容见图 3,由图可知,文件a.txt的内容正确无误的拷贝到了文件b.txt中,故程序运行结果完全正确。图 3执行mycopy后b.txt的内容(二) 编一个C程序,其内容为分窗口同时显示三个并发进程的运行结果。要求用到Linux下的图形库。a) 任务分析通俗的讲,程序是一个包含可以执行代码的文件 ,是一个静态的文件。而进程是一个开始执行但是还没有结束的程序的实例。一个程序可能有许多进程,而每一个进程又可以有许多子进程.依次循环下去,而产生子孙进程.为了区分各个不同的进程,系统给每一个进程分配了一个ID(就象我们的身份证)以便识别. 为了充分的利用资源,系统还对进程区分了不同的状态,将进程分为新建,运行,阻塞,就绪和完成五个状态。当一个进程调用了fork以后,系统会创建一个子进程.这个子进程和父进程不同的地方只有他的进程ID和父进程ID,其他的都是一样,就像父进程克隆(clone)自己一样。当然创建两个一模一样的进程是没有意义的。为了区分父进程和子进程,我们必须跟踪fork的返回值. 当fork调用失败的时候(内存不足或者是用户的最大进程数已到)fork返回-1,否则fork的返回值有重要的作用.对于父进程fork返回子进程的ID,而对于fork子进程返回0.我们可以根据这个返回值来区分父子进程。编译GTK程序与编译普通的C程序需要用到不同的命令。比如程序名为threeproc,则编译命令为:gcc pkg-config cflags -libs gtk+-2.0threeproc.c o threeproc。其中pkgconfig读取GTK附带的.pc文件来决定编译GTK程序需要的编译选项,pkgconfig -cflags gtk+-2.0列出include目录,pkgconfig -libs gtk+-2.0列出编译连接库。命令中的单引号是键盘上“1”键前面的那个,而不是回车键左边的那个,否则会出错。-libs、-cflags中都是两个横线。b) 程序源代码见显示三个并发进程的源程序c) 程序运行结果我写的程序有三个并发进程,并且分别利用三个窗口进行显示,显示框中各有一个进度条,但是其各自的刷新频率不一样,直观感受就是三个进度条不一致。窗口上面显示了各个进程的ID,可以看到三个进程的ID是不一样的。显示框中还有一个退出按钮,结果见图 4。图 4 三个并发进程的显示二、 掌握系统调用的实现过程,通过编译内核方法,增加一个新的系统调用。另编写一个应用程序,调用新增加的系统调用。a) 任务分析系统调用是应用程序和操作系统内核之间的功能接口,通过系统调用进程可由用户模式转入内核模式,在内核模式下完成相应的服务之后再返回到用户模式。系统调用的主要目的是使得用户可以使用操作系统提供的有关设备管理、输入/输出系统、文件系统和进程控制、通信以及存储管理等方面的功能,而不必了解系统程序的内部结构和有关硬件细节,从而起到减轻用户负担和保护系统以及提高资源利用率的作用。本次课设,我通过编译内核的方式,增加了一个系统调用,其功能为文件拷贝。b) 程序源代码见添加的系统调用源代码和测试程序c) 实验过程与步骤1、 wget source /.source code,下载linux源码,我下载的版本是linux-0.2、 sudo s,切换到root用户3、 tar -xjvf linux-0.解压内核到/usr/src/4、 打开/usr/src/linux-source-0/kernel/sys.c,在最后添加自己的系统调用程序sys_mycopy.注意把代码放在EXPORT_SYMBOL_GPL(orderly_poweroff);之前。5、 打开/usr/src/linux-source-2.6.35/arch/x86/kernel/syscall_table_32.s,然后在最后一行.long sys_XXXX的下一行添加.long sys_mycopy,并且后面的号码为系统调用号。我的是338.6、 打开/usr/src/linux-0/include/asm-generic/unistd.h,在#undef _NR_syscalls的前面加上#define _NR_mycopy 244_SYSCALL(_NR_mycopy, sys_mycopy)同时将#undef _NR_syscalls后面的数字加1.7、 编译内核首先进入解压目录:cd /usr/src/linux-source-2.6.35。运行命令make cleanmake menuconfigmake bzImagecp arch/x86/boot/bzImage /boomake modulesmake modules_installmake installcd /boot mkinitramfs -o initrd.img-0 0修改grub.cfg 增加一个启动项,代码如下:menuentry Ubuntu, with Linux 0 -class ubuntu -class gnu-linux -class gnu -class os recordfailinsmod part_msdosinsmod ext2set root=(hd0,msdos1)search -no-floppy -fs-uuid -set 64f525ed-3b34-4403-bb04-96bf47d14da1linux/boot/vmlinuz-0 root=UUID=64f525ed-3b34-4403-bb04-96bf47d14da1 ro quiet splashinitrd/boot/initrd.img-0set timeout=20重启计算机,选择新的内核进入。d) 程序运行结果开机显示新编译的内核,见图 5.图 5开机显示新编译的内核linux 0进入新的内核后,查看/usr目录下的文件a.txt见图 6。图 6文件a.txt的内容拷贝前b.txt的内容见图 7。图 7拷贝前文件b.txt的内容运行测试程序test_mycopy,将文件a.txt的内容拷贝到文件b.txt,结果见图 8。图 8拷贝后b.txt的内容三、 掌握增加设备驱动程序的方法。通过模块方法,增加一个新的设备驱动程序。a) 任务分析系统调用是操作系统内核和应用程序之间的接口,而设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件, 应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能:(1) 对设备初始化和释放.(2) 把数据从内核传送到硬件和从硬件读取数据.(3) 读取应用程序传送给设备文件的数据和回送应用程序请求的数据,检测和处理设备出现的错误。Linux支持三中不同类型的设备:字符设备(character devices)、块设备(block devices)和网络设备(network interfaces)。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作.块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。用户进程是通过设备文件来与实际的硬件打交道,每个设备文件都都有其文件属性(c/b),表示是字符设备还是块设备。另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们.设备文件的的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序。用户进程利用系统调用对设备进行诸如read/write操作,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数。最后,在用户进程调用驱动程序时,系统进入核心态,这时不再是抢先式调度.也就是说,系统必须在你的驱动程序的子函数返回后才能进行其他的工作。如果你的驱动程序陷入死循环,你只有重新启动机器了。我增加了一个字符设备驱动,可以将输入的字符串倒序输出。b) 程序源代码见添加新的设备驱动程序c) 实验过程与步骤将驱动源程序和Makefile文件放到 /桌面/mydriver 目录下,并切换到此目录编译,运行命令make,见图 9。图 9 编译如果成功,可以得到.ko文件接着挂载模块,运行命令 insmod rollover.ko,见图 10图 10 挂载模块创建新的虚拟设备文件,运行命令 mknod /dev/rollover c 100 0 (分配的设备号为100),见图 11图 11创建新的虚拟设备文件编写测试程序并测试。d) 程序运行结果编译测试程序后,运行,会提示输入字符串,输入之后按下回车键,可以看到字符串倒序输出,见图 12图 12测试结果由图 12可知,字符串倒序输出,故设备可以正常使用。四、 了解和掌握/proc文件系统的特点和使用方法(选做)a) 任务分析用户和应用程序可以通过/proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是动态从系统内核读出所需信息并提交的。我们要显示系统信息,只需进行相应的文件操作。首先打开相应的文件,读取所需要的信息,将其写入一个缓冲区中,然后将缓冲区的内容加到Gtk的相应的控件上面去,最后将控件组合显示即可。b) 程序源代码任务管理器源程序c) 程序运行结果任务管理器中显示的进程信息,见图 13图 13进程信息点击结束进程,会弹出对话框,确认是否结束当前进程,见图 14图 14结束进程对话框任务管理器中显示的系统信息 见图 15图 15系统信息任务管理器显示的内存资源信息,见图 16图 16内存资源任务管理器中显示的模块信息,见图 17图 17模块信息点击卸载模块,会弹出对话框,确认是否卸载选择的模块,见图 18图 18卸载模块对话框任务管理器中显示的帮助说明,见图 19图 19帮助说明点击退出程序,会弹出对话框,询问是否退出程序,见图 20图 20退出程序对话框点击关闭计算机,会弹出对话框,询问是否关闭计算机,见图 21图 21关闭计算机对话框点击重启计算机,会弹出对话框,询问是否重启计算机,见图 22图 22重启计算机对话框课设心得本次课设历时两个星期,由于上学期有过操作系统的实验基础,对Linux已经比较熟悉,所以这次课设开始时就比较顺利的完成了任务一中的第一小题。做到用图形界面显示三个进程时,我遇到了一点困难,因为从来没有接触gtk程序,一开始完全摸不着头脑。不过我相信自己可以自学好gtk,然后在百度文库下了一个gtk教程,自学了两天,觉得自己基本掌握了gtk的编程方法,可以编写一些简单的gtk程序了。但是编写完程序后,我猜发现,原来想要熟悉gtk并不是那么容易,一个简单的显示进程信息的程序我调试了半天,后来终于调试成功了,并且显示出了理想中的界面。这过程中我自己探索了很久,也请教了别人,可谓获益颇多。然后,做任务二的时候,我先在网上查询了一下,找到一个博客,网址是/kenjones/archive/2011/03/09/1978611.html 。里面详细介绍了添加系统调用的过程。起初我按照博主的步骤一一完成,经过接近三个小时的漫长编译过程后,新的内核可以进去,但是一运行测试程序,调用添加的系统调用,系统就会死机,我琢磨了半天也没弄清楚到底怎么回事。后来跟同学们讨论,发现原来是系统版本的问题。我用的系统版本是Linux-0,由于版本比较新,添加系统调用的方法有了一点改变,后来我按照网上的方法重新添加了系统调用,然后经过make bzImage(大约半个小时)后,重新进入新的内核,发现测试程序可以正常运行了,说明新的系统调用已经调用成功。这次实验过程可谓艰苦漫长,因为编译内核需要三个小时左右,刚开始又由于版本问题,我编译了两次内核,这个过程真是艰苦卓绝。不过还好后来没有出现大的问题,测试的过程比较顺利。这次实验让我印象深刻,因为过程比较漫长,确实需要很大的耐心。遇到自己不能解决的问题,可以尝试在网上寻找答案,或者和同学们一起讨论,这样可以让自己事半功倍。但是这绝不是坐享其果,在寻求帮助之前自己绝对要努力思考。任务三是添加新的字符设备,在了解了什么事设备以及Linux下设备的工作方式后,我按照老师给的PPT上的详解,同时也在网上找了如何添加设备驱动,然后按照步骤开始添加。不过我的添加方式并不是老师给的那种方法,而是自己在网上找的,因为开始按照老师的方法总有一点问题,后来按照网上的方法却成功了。这也告诉我们,遇到问题无法解决时,可以尝试一下多种方法,因为解决方法绝对不止一种,不能在一棵树上吊死。另外,这次的资源也是从网上找到的,互联网真是一个很奇妙的东西,各种思想都能相互交流,这也让我觉得,互联网绝不仅仅是用来娱乐的,它更多的是承载知识,以后一定要好好利用互联网,这样可以很大程度上提高学习效率。刚开始做任务四时,觉得好难好难,因为一点头绪也没有,而自己脑海中的任务管理器更是有着一层神秘的面纱。看了老师的指导书,才明白了任务管理器的原理,但是如何着手却仍是没有一个很清晰的认识。后来,我又尝试在网上寻找详细的资料,却发现了一个其他人做的任务管理器,我觉得可以借鉴一下别人的思想。仔细看了别人做的任务管理器,我脑海中的自己的任务管理器也愈发清晰起来。然后我借用了别人的框架,然后自己在上面添加了更多的功能,也优化了一下界面。其实,我找到的任务管理器十分的粗糙,有进程信息却没有结束进程的功能,有模块信息却没有卸载模块的功能,并且按照其CPU的使用率算法得到的结果和实际的结果有比较大的出入。后来,我把这些不足与缺陷都填补了。虽然,这次任务刚开始我借鉴了别人的成果,但是我并没有完全抄袭他人的成果。并且,我觉得适当的借鉴,可以开拓我们的视野,增长我们的见识。当然,原创的肯定是最好的,但是当你无法完全依靠自己的能力完成时,参考别人的意见或者成果,说不定可以让你产生灵感。并且,这是个思想自由的年代,需要人们的思想自由的沟通,集思广益才能让我们各自更上一层楼。由于任务四做完就已经临近检查时间了,并且老师的要求是任务四和任务五中选一个,我就没有再考虑任务五了。这次课设刚开始比较顺利,但是越往后就越是艰难,这种由浅入深的方式很适合我。并且,做完课设后,我对Linux的了解不知不觉由一种肤浅的认识,到了一定程度的娴熟。特别是一些关于系统内核的东西,以前觉得很是神秘,但是做完课设后,我对他们也有了一定的了解。我本来不是一个很喜欢向别人请教的人,遇到问题都喜欢自己解决,但是经过这次课设,我发现有时候与其自己一个人苦苦思索,不如大家一起来解决问题,思想上的交流是可以达到一加一大于二的效果的。很感谢这次课设,它带给我的不仅仅是知识,更是获得知识的方法。实验源程序一、 掌握Linux操作系统的使用方法,包括键盘命令、系统调用;掌握在Linux下的编程环境A. 实现文件拷贝的源程序#include #include #include #include #include #include #include #define BUFFER_SIZE 100 /缓冲区大小int main(int argc,char *argv)int from_fd,to_fd;int bytes_read,bytes_write;char bufferBUFFER_SIZE+1; /设定一个缓冲区char *ptr;if(argc!=3) /三个参数printf(Input error!n);return(-1);/* 打开源文件 */if(from_fd=open(argv1,O_RDONLY)=-1)printf(Open %s Error!n,argv1);return(-1);/* 打开或创建目的文件 */if(to_fd=open(argv2,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR)=-1)printf(Open %s Error!n,argv2);return(-1);while(bytes_read=read(from_fd,buffer,BUFFER_SIZE) /* 一个致命的错误发生了 */if(bytes_read=-1) break;else if(bytes_read0)ptr=buffer;while(bytes_write=write(to_fd,ptr,bytes_read)/* 一个致命错误发生了 */if(bytes_write=-1)&(errno!=EINTR)break;/* 写完了所有读的字节 */else if(bytes_write=bytes_read) break;/* 只写了一部分,继续写 */else if(bytes_write0)ptr+=bytes_write;bytes_read-=bytes_write;/* 写的时候发生的致命错误 */if(bytes_write=-1)break;close(from_fd);close(to_fd);return 1;B. 显示三个并发进程的源程序#include #include #include #include int timer;gboolean update_p_bar(gpointer pbar) gdouble new_val = 0.0; new_val = gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(pbar) + 0.005; if(new_val 1.0)gtk_timeout_remove(timer); return FALSE; gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pbar), new_val); return TRUE;void process(int argc, char *argv,int mark)gtk_init(&argc, &argv);GtkWidget *window, *vbox, *pid_label, *pbar;GtkWidget *button;GdkColor color;gdk_color_parse(red, &color);/* 创建窗口 */window = gtk_window_new(GTK_WINDOW_TOPLEVEL);gtk_window_set_title(GTK_WINDOW(window), 并发进程结果显示);/设置标题gtk_window_set_default_size(GTK_WINDOW(window), 400, 200);/设置大小g_signal_connect(G_OBJECT(window), destroy, G_CALLBACK(gtk_main_quit), NULL);/* 创建垂直组装盒 */vbox = gtk_vbox_new(FALSE, 5);gtk_container_add(GTK_CONTAINER(window), vbox); /* 创建标签 */char s_pid40;sprintf(s_pid, 进程%d 此进程ID为:%d , mark,getpid();pid_label = gtk_label_new(s_pid); gtk_container_add(GTK_CONTAINER(vbox), pid_label); /* 创建进度条 */pbar = gtk_progress_bar_new();gtk_container_add(GTK_CONTAINER(vbox), pbar);int interval = atoi(argv0);timer = gtk_timeout_add(interval, update_p_bar, pbar); /*创建退出按钮*/button = gtk_button_new_with_label (Exit);gtk_widget_modify_bg(button, GTK_STATE_NORMAL, &color);gtk_container_add(GTK_CONTAINER(vbox), button);g_signal_connect_swapped (G_OBJECT (button), clicked,G_CALLBACK (gtk_main_quit),window);gtk_widget_show_all(window);gtk_main ();int main(int argc, char *argv)pid_t pid_1, pid_2;char *argvv1;int mark;pid_1 = fork();if(pid_1 = -1)/创建失败printf(Create progress error!); else if(pid_1 = 0)/子进程pid_2 = fork();if(pid_2 = -1)/创建失败printf(Create progress error!); else if(pid_2 = 0)/子进程mark=3;argvv0 = 400;process(1, argvv,mark);else/父进程mark=2;argvv0 = 200;process(1, argvv,mark);else/父进程mark=1;argvv0 = 800;process(1, argvv,mark);return 0;二、 增加一个新的系统调用A. 添加的系统调用源代码SYSCALL_DEFINE2(mycopy,char *,from_file, char *,to_file)int from_fd, to_fd;int bytes_read,bytes_write;char buffer2; /缓冲区mm_segment_t old_fs;old_fs = get_fs();set_fs(KERNEL_DS);if(from_fd=sys_open(from_file,O_RDONLY,0)=-1) /打开源文件return 0;if(to_fd=sys_open(to_file,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR)=-1) /打开目标文件 return 0; while(bytes_read=sys_read(from_fd,buffer,1) /循环读一个字节直到文件尾 if(bytes_read=-1) return 0; /一个致命的错误发生了 if(bytes_read0) bytes_write=sys_write(to_fd,buffer,bytes_read); /写一个字节if(bytes_write=-1)return 0; / 一个致命错误发生了 set_fs(old_fs);sys_close(from_fd); /关闭文件sys_close(to_fd); /关闭文件return 1;B. 测试程序#include #include #include #include #include #include #include int main(int argc,char *argv)int from_fd,to_fd;if(argc!=3) /三个参数 printf(Input error!n); return(-1); else if(syscall(338,argv1,argv2)printf(Successful!n); /系统调用号为338else printf(Failed!n); return 1;三、 添加新的设备驱动程序A. 驱动源程序#include #include #include #include #include #include #define MAJOR_NUM 100 MODULE_LICENSE(GPL);MODULE_AUTHOR(HQM);char buffer1024; static ssize_t char_read(struct file *, char*, size_t, loff_t *);static ssize_t char_write(struct file *, const char*, size_t, loff_t *);struct file_operations char_fops=read:char_read, write:char_write,;static int char_init(void) /注册字符设备if(register_chrdev(MAJOR_NUM, rollover, &char_fops)printk(rollover register failuren);return 1;elseprintk(rollover register successn);return 0;static void char_exit(void) /注销字符设备unregister_chrdev(MAJOR_NUM, rollover);static ssize_t char_read(struct file *filp, char *buf, size_t len, loff_t *off) /字符设备的读操作printk(nread in:%sn, buf);if(copy_to_user(buf, buffer, len) /将文件内容读到缓冲区bufreturn 0;return true;static ssize_t char_write(struct file *filp, const char*buf, size_t len, loff_t *off) /字符设备的写操作int i = 0;char templen; /缓存区temp大小if(copy_from_user(temp, buf, len) /将内容拷贝到缓冲区tempreturn 0;while(i len-1) /将temp内容倒序写入bufferbufferlen-i-2=tempi;i+;printk(nwrite out:%c, bufferlen-i);return true;module_init(char_init);module_exit(char_exit);B. 文件Makefile内容ifneq ($(KERNELRELEASE),) #kbuild syntax.#模块的文件组成#mymodule-objs :=rollover.o #生成的模块文件名 obj-m := rollover.o elsePWD :=$(shell pwd)KVER :=$(shell uname -r)KDIR :=/lib/modules/$(KVER)/buildall:$(MAKE) -C $(KDIR) M=$(PWD)clean:#rm -f *.cmd *.o *.mod *.korm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions#$(MAKE) -C $(KDIR) M=$(PWD) cleanEndifC. 测试程序#include #include #include #include void main(void)int fd;int count=0;char buf1024; /缓冲区大小fd = open(/dev/rollover, O_RDWR, S_IRUSR | S_IWUSR); /打开字符设备文件if (fd != -1 )printf(please input letters:); /用户输入字符串scanf(%s, buf);while(bufcount+) /count为字符串长度;if(write(fd,buf, count) /向字符设备文件写入字符串if(read(fd,buf, count) /从字符设备文件读出字符串printf(The letters is: %sn, buf);elseprintf(Read Error!n);elseprintf(Write Error!n);close(fd); /关闭字符设备文件else /打开字符设备错误的情况printf(Device open failuren);四、 任务管理器源程序A. 任务管理器源程序#include #include #include #include #include #include #include #include #include #include #include #include #include #define GTK_ENABLE_BROKEN/在文本构件中使用int read_proc();/读取proc文件内容int timeout_refresh();/时间刷新函数char *strcut(char *main_str, char *sub_str);/取字符串char *findstr(char *mainstr,int n); /查找字符串void on_button_H_clicked (GtkWidget *button,gpointer userdata); /关机的对话框void on_button_G_clicked (GtkWidget *button,gpointer userdata); /重启的对话框void on_button_E_clicked (GtkWidget *button,gpointer userdata); /退出的对话框void on_button_P_clicked (GtkWidget *button,gpointer userdata); /结束进程的对话框void on_button_M_clicked (GtkWidget *button,gpointer userdata); /卸载模块的对话框void kill_proc(void);void uninst_mod(void);static char pro_buf256532;/进程信息static char *pro_pid; /进程pidstatic char *mod_name;/模块名static char sys_buf210196;/系统信息static char mm_buf10196;/内存信息static char module_buf256332;/模块信息static char cpu_buf2561032; /cpu信息static int pro_row;static int mod_row;static int temp_pro;/当前进程数static int pre_pro;static int run_pro=1; /运行进程数static int temp_module;/当前模块数static i
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- NBT 11197-2023 输变电工程三维设计技术导则
- DLT 5393-2023 高压直流换流站接入系统设计内容深度规定
- 化妆师考试题及答案
- 广誉远中药招聘试题及答案
- 公务员面试塑面试题及答案
- 公务员面试目面试题及答案
- 会计招聘笔试题及答案
- 恒瑞医药秋招面试题及答案
- 公务员面试考上公务员面试题及答案
- 公务员面试纪律面试题及答案
- 管制刀具班会课件
- 汽修维修记录管理制度
- JG/T 528-2017建筑装饰装修材料挥发性有机物释放率测试方法-测试舱法
- 林火监测与预警课件
- 会计中级职称《财务管理》电子书
- 学生学业成绩分析与进步跟踪表
- 2025年驾驶证资格考试科目一必刷题库及答案(共420题)
- 体育场馆羽毛球馆运营策略考核试卷
- 国开公共部门人力资源管理自检自测1-九
- 红旗河工程可行性报告
- 光伏区围栏施工方案
评论
0/150
提交评论