2022年Linux编程练习 .pdf

上传人:Che****ry 文档编号:27265605 上传时间:2022-07-23 格式:PDF 页数:11 大小:88.11KB
返回 下载 相关 举报
2022年Linux编程练习 .pdf_第1页
第1页 / 共11页
2022年Linux编程练习 .pdf_第2页
第2页 / 共11页
点击查看更多>>
资源描述

《2022年Linux编程练习 .pdf》由会员分享,可在线阅读,更多相关《2022年Linux编程练习 .pdf(11页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、1简单的内核程序#include /* * Kernel program needs this head file */#include /* * the PCB task_struct structures is defined * in the */#include #include /* * LSM related definitions are in this head file */#include MODULE_LICENSE( GPL); MODULE_AUTHOR( YOUR NAME ); MODULE_DESCRIPTION( Kernel Study); /* exter

2、n int register_security(struct security_operations *ops); */* * Parameters of the module (the pid of the process to be modify) */intproc2check = 0; module_param( proc2check, int, S_IRUGO); charfilename256= 0; int secondary = 0; /* static inline int file_integrity_check_security(struct linux_binprm *

3、bprm) strcpy(filename, bprm-interp); printk(KERN_ALERT the file to be run is: %sn, filename); / To do: Add code about file integrity check here 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 11 页 - - - - - - - - - return 0; */* static struct security_operations

4、 kernel_security_ops = .bprm_check_security = file_integrity_check_security, ; */staticint process_op (void) / * * Linux 所有进程用 struct list_head链接起来,构成双向循环链表。* 这里使用 prev、this、 temp和next对双向循环链表进行操作。*/ struct list_head *prev, *this, *next, *temp; /* * 双向循环链表中所链接起来的每一个PCB */ struct task_struct *proc; /*

5、 * 得到当前正在运行进程的双向链表链接结构tasks。* tasks定义为: struct list_head *tasks; */ this = (struct list_head *)&( current-tasks); /current是当前的进程temp = this; /将当前进程 PCB的tasks结构保存prev = this-prev; /得到当前运行进程的前一个链接进程PCB当中的 tasksnext = this-next; /得到当前运行进程的后一个链接进程PCB当中的 tasks/* * (1)开始遍历用tasks所链接起来的双向循环链表。查询指定PCB,并进行处理。

6、* (2)注意: container_of从tasks结构得到 tasks所在结构体的首地址*/ while(container_of(this, struct task_struct, tasks)-pid) != proc2check) printk(KERN_ALERT current pid is: %dn, container_of(this, structtask_struct, tasks)-pid); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 11

7、页 - - - - - - - - - / 没有找到,则查询下一个双向循环链表节点prev = this; this = next; next = next-next; /* * temp 是前面存储的遍历起点。如果当前的节点与遍历起点相同,说明整个链表已经遍历* 完毕,跳出循环;否则继续遍历*/ if (this != temp) continue; elsebreak; /* *如果是因为没有找到proc2check所指定的进程,则打印:pid未找到*/ if (this = temp) printk(KERN_ALERT pid error!n ); return -1; /* * pr

8、int the state of the process identified by variable proc2check */ /* 根据当前的 this指针( struct task_struct结构体内部的 struct list_head* tasks )* 计算 this所在结构体的首地址,也就是pid为proc2check进程的 PCB首地址。*/ proc = container_of(this, struct task_struct, tasks); if (proc-state state = 0) printk(KERN_ALERT process with pid %d

9、 is currently runnable.n, proc2check ); elseprintk(KERN_ALERT process with pid %d is currently stopped.n , proc2check ); /* * delete the process from the task_struct 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 11 页 - - - - - - - - - */ /* * 将pid为proc2check的进

10、程从双向循环链表当中删除*/ prev-next = next; next-prev = prev; printk(KERN_ALERT process with pid %d is deleted from the PCBn. , proc2check ); return 0; staticint hello_init(void) printk(KERN_ALERT Hello, world!n ); /* * Register LSM hooks if (register_security(&kernel_security_ops) printk(KERN_ALERT Failure re

11、gistering the LSM module!n); return -1; */process_op (); return 0; staticvoid hello_exit(void) printk(KERN_ALERT Goodbye, cruel world!n ); module_init(hello_init); module_exit(hello_exit); 代码说明:(1)内核模块的参数。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 11 页 - -

12、- - - - - - - 参数可以使用module_param宏声明, 这个宏定义在 moduleparam.h 当中。module_param带3个参数:变量名、类型和权限。其形式为:module_param(变量名 , 类型 , 权限 )。宏应该放在任何函数的外面,放在接近源文件的头部。module_param 宏参数支持如下类型:bool、invbool(将真变假,假变真) 、charp(字符指针) 、int、long、short、uint、ulong、ushort 、数组。当使用数组的时候,数组值用逗号分开作为列表。最后的模块参数是一个访问权限,参见 。S_IRUGO可读不可改变;

13、S_IRUGO | S_IWUSR允许 root 改变参数。 注意:如果参数被sysfs改变了, 除非你的内核发现了改变,否则内核没有任何办法感知该改变。你很可能不应该设置内核模块参数可写,除非你准备探测这种改变并且相应作出调整。(2)task_struct数据结构。进程属性相关的域。包括: state, pid, flag, binfmt, exit_code and exit_signal, common(命令行调用时, 可执行文件的名字 ), ptrace(调用系统调用ptrace时置位 )等。进程调度相关的域。包括: prio, run_list, array( 优先级数组 ), sl

14、eep_avg, timestamp, interactive_credit, policy( 采用时间片轮转或者实时调度方式), cpus_allowed, time_slice 等。进程关系相关的域。包括: real_parent, prent, children, sibling, group_leader 等。进程证书相关的域。包括: uid和gid, euid和egid, suid和sgid, group_info 等。进程权能相关的域。将uid=0的权限进行分割。包括: cap_effective, cap_inheritable, cap_permitted 等。进程限制相关的域

15、。包括: rlim( 资源限制 )等。进程文件系统或者地址空间相关的域。包括: fs, files, mm( 内存管理 ), active_mm( 最近最常访问的地址空间) (3)container_of函数。原型:#define container_of(ptr, type, member) ( const typeof( (type *)0)-member ) *_mptr = (ptr); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 11 页 - - - - -

16、 - - - - (type *)( (char *)_mptr - offsetof(type,member) );) 第一行:定义 containter_of 宏;第二行:强制类型转换将ptr转化为类型为type的结构体内部成员member的类型;第三行:计算 ptr所在结构体的首地址将ptr减掉它到结构体头部的偏移大小(offsetof(type, member)),即得到 ptr所在的结构体的首地址。(4)链表的构建。链表的创建:malloc函数使用;插入一个节点到链表;如何创建一个新链表:主要注意头结点是否为空的问题。链表的删除:如何删除一个节点;malloc/free 的配对使用;

17、链表的遍历单向链表的遍历;单向循环链表的遍历。作业:双向循环链表创建、插入、删除、遍历、销毁。(5)LSM 编写和 LSM 钩子类型。使用 register_security函数进行注册。所有的 lsm 钩子在: /usr/src/Linux 版本 /include /linux/security.h里面。可以从里面查询。钩子的类型有:task_struct 结构:代表任务(进程)linux_binprm 结构:代表程序super_block 结构:代表文件系统inode 结构:代表管道,文件,或者Socket套接字file 结构:代表打开的文件sk_buff 结构:代表网络缓冲区(包)net

18、_device 结构:代表网络设备kern_ipc_perm 结构:代表Semaphore 信号,共享内存段,或者消息队列msg_msg:代表单个的消息名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 11 页 - - - - - - - - - 2 task_struct结构的内容1 进程 PCB的具体定义具体在“includelinuxsched.h ” 。(1)上 www.kernel.org 下载 Linux 源码;(2)搜寻“struct task_struct

19、” ,可以找到task_struct 结构体的内容。这就是进程PCB的定义。2 本次用到了state。state 表示了当前进程的状态:-1 不可运行; 0 可以运行; 0停止运行。3 进程是通过双向循环链表struct list_head 链接起来的。struct list_head 结构可以在“includelinuxlist.h”当中找到。其定义如下:structlist_head structlist_head * next, *prev ; ; 它就是两个指针,一个前向指针,一个后项指针。在 task_struct 结构体内部用struct list_head tasks; 将所有进

20、程的PCB 链接起来,构成双向循环链表。4 PCB当中包含的信息参见 Linux 内核编程必读名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 11 页 - - - - - - - - - 3Linux程序编写(1)下载最新的vim hdzfhdzf-desktop: sudo apt-get install vim (2)编写 vim 的配置文件hdzfhdzf-desktop: cd hdzfhdzf-desktop: ls a 找到名为 .vimrc的文件。如果没有,

21、则:hdzfhdzf-desktop: vi .vimrc 进入之后:先按i ,进入输入状态。注意:vim 在命令模式和输入模式之间转换。如果你当前是在输入模式,按两次ESC,则进入命令模式,此时你可以用“:+ 命令”的方式来输入编辑命令。如果此时是命令状态,你可以按i进入输入模式,从光标所在处进行输入;你也可以按“ A” ,从而从一行的末尾开始输入。这里按“ i ”或者“ A” ,进行输入:set nocompatible set sm set tabstop=4 set number 然后,按两次ESC,进入命令状态。按“:wq ”命令存盘退出。输入 exit退出 shell hdzfhd

22、zf-desktop: exit 启动一个新的shell,此时, vim 会自动运行 .vimrc 配置文件,按我们的配置进行运行。(3)进行第一个 .c 程序的编写#include “stdio.h”void main(void) printf(“hello world!n”);return; (4)编译第一个可执行程序(man gcc,或者找gcc使用手册)名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 11 页 - - - - - - - - - 编译采用 gcc工

23、具。架设你前面的文件名为hello.c,则输入命令:hdzfhdzf-desktop: gcc g o hello hello.c 编译成功之后生成一个名为hello的文件。运行:hdzfhdzf-desktop: ./hello (5)调试工具。软件调试的艺术hdzfhdzf-desktop: gdb ./hello (gdb) list (gdb) break 5 (gdb) run (gdb) quit名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 11 页 - -

24、 - - - - - - - 4Linux内核编译详细信息可见:http:/ /boot/vmlinuz- :用于启动的压缩内核镜像, 它也就是 /arch/boot中的压缩镜像 . /boot/system.map- :存储内核符号地址. /boot/initrd.img-:初始化RAM 硬盘时 , 用来存储挂载根文件系统所需的模块. /boot/grub/menu.lst:grub 的配置文件 . (不同的发行版中它可能位于不同位置. /lib/modules :该目录包含了内核模块及其他文件. 注意 , modules 中一般会有多个目录: 系统自带的内核模块在这里, 你编译自己的内核模

25、块后, 它们也会被安装到这里. 不同的目录由内核版本号来区分. 即 modules 里目录的名称是内核版本号. (使用 $ uname -r 可知当前系统内核所用的模块位于哪个目录). /lib/modules/build:储存为该版本的内核编译新模块所需的文件. 包括Makefile, .config, module.symVers( 模块符号信息 ), 内核头文件 (位于 include/, include/asm/ 中) /lib/modules/kernel:储存内核目标文件(以.ko 为后缀 ). 它的目录组织和内核源代码中kernel 的目录组织相同. /lib/modules/中

26、: modules.alias 定义了模块别名定义. 模块加载工具使用它来加载相应的模块;modules.dep 定义了模块间的依赖关系;modules.symbols 指定符号属于哪个模块 . 这些文件都是文本文件, 可以查看它们. (2)验证签名。首先从 pgp 的服务器获取签名公匙, linux 内核包的公匙编号是0 x517D0F0E. 再利用 sign文件来验证 .bz2 压缩包的签名. 如果输出中有类似gpg: Good signature from Linux Kernel Archives Verification Key 的内容 , 说明该包是有效的. 后面给出的警告信息可以

27、忽略. $ gpg -keyserver -recv-keys 0 x517D0F0E $ gpg -verify linux-2.6.17.13.tar.bz2.sign linux-2.6.17.13.tar.bz2 (3)开始编译:首先构建编译环境:sudo apt-get install build-essential 找到具有Makefile的目录,以Linux2.6.36 内核为例(下同) ,该目录可能为:/usr/src/linux-2.6.36 ,命令如下:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心

28、整理 - - - - - - - 第 10 页,共 11 页 - - - - - - - - - cd /usr/src/linux-2.6.36 配置内核: sudo make menuconfig make 相关命令$ make oldconfig : 基于已有的 .config 进行配置 , 若有新的符号, 它将询问用户. $ make defconfig : 按默认选项对内核进行配置(386 的默认配置是Linus 做的 ). $ make allnoconfig : 除必须的选项外, 其它选项一律不选. (常用于嵌入式系统). $ make clean : 删除生成的目标文件, 往往

29、用它来实现对驱动的重新编译. $ make mrproper : 删除包括 .config 在内的生成的目标文件. 可以查看内核源码树中的README和 Makefile 了解上述配置方法. make make modules make modules_install make install 进行安装修改启动项,拷贝启动文件:将“ /usr/src/linux 版本号 /arch/x86/boot/”目录下的bzImage 拷贝到“ /boot/ ”目录下。以2.6.36 版本为例(下同) ,命令为:sudo cp /usr/src/linux-2.6.36/arch/x86/boot/bz

30、Image /boot 利用“ mkinitramfs o /boot/initrd.img-版本号”命令生成Initrd 文件。命令为:sudo cp /usr/src/linux-2.6.36/initrd.img-2.6.36 /boot 更新 /boot/grub/menu.lst文件,加入新的启动菜单。利用 updatge-grub 更新 gurb。重新启动,选择启动菜单。进入后,利用uname r 命令查看当前内核版本号。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 11 页,共 11 页 - - - - - - - - -

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高考资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁