收藏 分销(赏)

西电Linux内核分析大作业.doc

上传人:精**** 文档编号:2773466 上传时间:2024-06-05 格式:DOC 页数:6 大小:444.65KB 下载积分:6 金币
下载 相关 举报
西电Linux内核分析大作业.doc_第1页
第1页 / 共6页
西电Linux内核分析大作业.doc_第2页
第2页 / 共6页


点击查看更多>>
资源描述
Linux内核作业 一、 程序设计思路 题目中说明要使用系统调用,所以首先要先下载编译Linux内核,并在内核中加入相关的系统调用声明,序号等等的。 进程是通过list_head双向链表连接起来的,所以根据一个进程就可以得到其他的进程描述符。要获得第一个进程,我们选择了init进程。要把进程以树的形式输出,所以要用到深度优先遍历。在进程描述符中,通过children可以获得这个进程的子进程。根据优先遍历的方法,进行递归的打印输出,就可以生成一棵进程树。打印过程中,缩进采用层级的打印空格实现。 二、 程序内容 程序中首先要在一些表中进行声明。 主要的程序在sys.c中实现。主要有两个函数构成,一个系统调用函数,一个用于递归调用的函数。 在系统调用函数中,会调用这个递归调用函数。 三、 问题及解决办法 1. 不了解进程描述符 struct task_struct { //这个是进程的运行时状态,-1代表不可运行,0代表可运行,>0代表已停止。 volatile long state; /* flags是进程当前的状态标志,具体的如: 0x00000002表示进程正在被创建; 0x00000004表示进程正准备退出; 0x00000040 表示此进程被fork出,但是并没有执行exec; 0x00000400表示此进程由于其他进程发送相关信号而被杀死 。 */ unsigned int flags; //表示此进程的运行优先级 unsigned int rt_priority; struct list_head tasks; //该结构体记录了进程内存使用的相关情况 struct mm_struct *mm; /*进程的一些状态参数*/ int exit_state; int exit_code, exit_signal; //进程号 pid_t pid; //进程组号 pid_t tgid; //real_parent是该进程的“亲生父亲”,不管其是否被“寄养”。 struct task_struct *real_parent; //parent是该进程现在的父进程,有可能是“继父” struct task_struct *parent; //这里children指的是该进程孩子的链表,可以得到所有孩子的进程描述符 struct list_head children; //sibling该进程兄弟的链表,也就是其父亲的所有孩子的链表 struct list_head sibling; //这个是主线程的进程描述符 struct task_struct *group_leader; //这个是该进程所有线程的链表。 struct list_head thread_group; //该进程使用cpu时间的信息,utime是在用户态下执行的时间,stime是在内核态下执行的时间 cputime_t utime, stime; //下面的是启动的时间,只是时间基准不一样 struct timespec start_time; struct timespec real_start_time; //comm是保存该进程名字的字符数组,长度最长为15,因为TASK_COMM_LEN为16 char comm[TASK_COMM_LEN]; /* 文件系统信息计数*/ int link_count, total_link_count; /*该进程在特定CPU下的状态*/ struct thread_struct thread; /* 文件系统相关信息结构体*/ struct fs_struct *fs; /* 打开的文件相关信息结构体*/ struct files_struct *files; /* 信号相关信息的句柄*/ struct signal_struct *signal; struct signal_struct *signal; /*这些是松弛时间值,用来规定select()和poll()的超时时间,单位是纳秒nanoseconds */ unsigned long timer_slack_ns; unsigned long default_timer_slack_ns; }; 2. 遍历进程的方法 #define list_entry(ptr,type,member)\   container_of(ptr,type,member) #define offsetof(TYPE,MEMBER) ((size_t)&((TYPE *)0)->MEMBER) #define container_of(ptr,type,member) ( {\   const typeof( ((type*)0)->member ) *__mptr=(ptr);\   (type*)( (char*)__mptr - offsetof(type,member) );} ) #define list_for_each(pos, head) \ for (pos = (head)->next; prefetch(pos->next), pos != (head); \ pos = pos->next) 通过这些宏,知道了如何去使用这些宏进行遍历。 四、 代码及说明 1. arch/x86/kernel/syscall_table_32.S .long sys_yyycall 2. arch/x86/include/asm/unistd_32.h #define __NR_yyycall 337 #ifdef __KERNEL__ #define __NR_syscalls 338 3. include/linux/syscalls.h asmlinkage long sys_yyycall(void); 4. kernel/sys.c //task表示当前的进程描述符,n表示多少层 static void print_child(struct task_struct* task,int n) { //链表指针 struct list_head *pos; //进程描述符的指针 struct task_struct* p; //临时变量i,用于输出空格 int i; for(i=n;i>0;i--) printk(" "); //输出进程树 printk("|————%d\n",task->pid); //遍历子进程 list_for_each(pos,&task->children) { //根据list_head获取进程 p=list_entry(pos, struct task_struct,sibling); if(p!=NULL) { n++; //递归调用 print_child(p,n); n--; } } } asmlinkage long sys_yyycall(void) { printk("********************************************\n\n"); //以init进程为初始进程,运行递归调用程序 print_child(&init_task,0); printk("********************************************\n\n"); return 1; } 5. 用户程序linux.c #include<stdio.h> int main() { //调用了337系统调用,并获得返回值 int a = syscall(337); printf(“%d”,a); return 0; } 五、 运行结果及说明 首先对内核进行编译,重启。 然后编译用户程序,并运行,输出返回值为1。 可以用dmesg查看系统日志,可以观察到结果是以树的形式展示。 六、 运行截图 运行结果如图所示。
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服