操作系统课内报告 内核编译、系统调用和进程同步通信 - 图文

2025/5/5 3:45:30

操作系统课内实验报告

2.3.1 structtask_struct

进程的内核数据结构是task_struct结构,它使用两个指针next_task和prev_task将各个进程连成一个循环双链表,相应的指针p_opptr、p_pptr、p_cptr、p_ysptr和p_osptr来表示进程之间的家族关系。

structtask_struct //进程描述符。 {

long state; //任务的运行状态(-1 不可运行,0 可运行(就绪),>0 已停止)。 long counter; // 任务运行时间计数(递减)(滴答数),运行时间片。

long priority; //运行优先数。任务开始运行时counter = priority,越大运行越长。 long signal; //信号。是位图,每个比特位代表一种信号,信号值=位偏移值+1。 structsigactionsigaction[32]; // 信号执行属性结构,对应信号将要执行的操作和标志信息。 long blocked; //进程信号屏蔽码(对应信号位图)。 intexit_code; //任务执行停止的退出码,其父进程会取。 unsigned long start_code; // 代码段地址。

unsigned long end_code; // 代码长度(字节数)。

unsigned long end_data; // 代码长度 + 数据长度(字节数)。 unsigned long brk; // 总长度(字节数)。 unsigned long start_stack; // 堆栈段地址。 long pid; // 进程标识号(进程号)。 long father; // 父进程号。 long pgrp; // 父进程组号。 long session; // 会话号。 long leader; // 会话首领。

unsigned short uid; //用户标识号(用户id)。 unsigned short euid; // 有效用户id。 unsigned short suid; // 保存的用户id。 unsigned short gid; // 组标识号(组id)。 unsigned short egid; // 有效组id。 unsigned short sgid; // 保存的组id。 long alarm; // 报警定时值(滴答数)。 long utime; // 用户态运行时间(滴答数)。 long stime; // 系统态运行时间(滴答数)。 long cutime; // 子进程用户态运行时间。 long cstime; // 子进程系统态运行时间。 long start_time; // 进程开始运行时刻。

unsigned short used_math; // 标志:是否使用了协处理器。 inttty;// 进程使用tty的子设备号。-1 表示没有使用。 unsigned short umask; // 文件创建属性屏蔽位。 structm_inode * pwd; // 当前工作目录i节点结构。 structm_inode * root; // 根目录i节点结构。

structm_inode * executable; // 执行文件i节点结构。

unsigned long close_on_exec; // 执行时关闭文件句柄位图标志。(参见include/fcntl.h) struct file * filp[NR_OPEN]; // 进程使用的文件表结构。

structdesc_structldt[3]; // 本任务的局部表描述符。0-空,1-代码段cs,2-数据和堆栈段ds&ss。

structtss_structtss; // 本进程的任务状态段信息结构。 2.3.2 task

task 定义为指向structtask_struct结构的指针数组,这个数组的每个项代表系统中的一

9

操作系统课内实验报告

个任务。数组的大小是NR_TASKS,它规定了系统中同时可以运行的任务的数量。

externstructtask_struct *task[NR_TASKS]; 2.3.3 tarray_freelist

自由时间片列表tarray_freelist拥有一个说明task 数组中自由位置的列表,即当前没有被使用的空位置。

structtask_struct **tarray_freelist; 2.3.4 struct--linux_binprm

内核中为可执行程序的装入定义了一个数据结构linux_binprm,以便将运行一个可执行文件时所需的信息组织在一起。

/usr/src/linux/include/linux/binfmts.h

structlinux_binprm{

charbuf[BINPRM_BUF_SIZE];

struct page * page[MAX_ARG_PAGES]; structmm_struct * mm;

unsigned long p; /* current top of mem */ intsh_bang;

struct file * file; inte_uid, e_gid;

kernel_cap_tcap_inheritable, cap_permitted, cap_effective; void * security; intargc, envc;

char * filename; /* Name of binary as seen by procps */ char * interp; /* Name of the binary really executed. Most of the time same as filename, but could be different for binfmt_{misc,script} */ unsignedinterp_flags; unsignedinterp_data;

unsigned long loader, exec; };

#ifdef __KERNEL__#define MAX_ARG_PAGES 32

linux_binprm->page[]

每个参数的最大长度为一个物理页面,所以linux_binprm中有个页面指针数组,数组的大小为允许的最大参数个数MAX_ARG_PAGES,目前这个常数定义为32。 2.3.5进程状态

TASK_RUNNING:运行状态;

TASK_INTERRUPTIBLE:等待状态可以让其他进程唤醒; TASK_UNINTERRUPTIBLE:等待状态但不让其他进程唤醒; TASK_ZOMBIE:进程已经结束执行但尚未消亡;

TASK_STOPPED:进程暂停用其他进程的信号才能唤醒; TASK_SWAPPING:被换出的进程。

10

操作系统课内实验报告

2.4常量和出错信息的意义

#define NR_TASKS 64 // 系统中同时最多任务(进程)数。

#define HZ 100 // 定义系统时钟滴答频率(1 百赫兹,每个滴答10ms) #define FIRST_TASK task[0] // 任务0 比较特殊,所以特意给它单独定义一个符号。 #define LAST_TASK task[NR_TASKS-1] // 任务数组中的最后一项任务。 #define TASK_RUNNING 0 // 进程正在运行或已准备就绪。 #define TASK_INTERRUPTIBLE 1 // 进程处于可中断等待状态。

#define TASK_UNINTERRUPTIBLE 2 // 进程处于不可中断等待状态,主要用于I/O 操作等待。

#define TASK_ZOMBIE 3 // 进程处于僵死状态,已经停止运行,但父进程还没发信号。

#define TASK_STOPPED 4 // 进程已停止。

2.5各模块/函数详细框图

2.5.1 do_fork模块

当进程调用fork时,该进程从概念上被分成两部分—祖先和子孙可以自由选择不同飞路径。在fork之后,祖先进程和其子进程几乎是等同的,它们所有的变量都有相同的值,它们打开的文件都相同,等等。但是如果祖先进程改变了一个变量的值,子进程看不到这个变化,反之亦然,子进程是祖先进程的一个拷贝,但它们并不共享内存内容。

linux保留了传统的fork并增加了一个更加通用的函数__clone。鉴于fork创建一个新进程的子孙进程后。子孙进程虽然是祖先进程的拷贝,但是它们并不共享内容,__clone允许你定义祖先进程和子进程所应该共享的内容,如果你没有给__clone提供它所能识别的五个标志,子孙进程和祖先进程就不会共享任何内容,这就和传统fork类似。如果你提供了全部的五个标志,子孙进程就可以和祖先进程共享任何内容,这就和传统的线程类似,其他标记的不同组合可以使你完成介于两者之间的功能。

给新进程一个 分配新的进程控制快并给新的进程控制快赋值 设置进程之间的家族信息 把新进程放到Pidhash表中 把进程设置为TASK_RUNNING状态 图2.1 do fork 函数流程图 11

操作系统课内实验报告

long do_fork(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size, int __user *parent_tidptr, int __user *child_tidptr) {

struct task_struct *p; int trace = 0; long nr;

if (unlikely(clone_flags & CLONE_STOPPED)) { /*

*如果在clone_flags中设置了CLONE_PID标志,就返回一个错误(-EPERM)。

*因为CLONE_PID有特殊的作用,当这个标志为1时,父,子进程(线程)共用一个进程号 *即子进程虽然有自己的task_struct结构,却使用父进程的pid. *但是只有0号进程(即系统中的空线程)才允许使用这个标志。 */ } /*

* When called from kernel_thread, don't do user tracing stuff. */

if (likely(user_mode(regs)))

p = copy_process(clone_flags, stack_start, regs, stack_size,

12

static int __read_mostly count = 100;

if (count > 0 && printk_ratelimit()) { }

char comm[TASK_COMM_LEN]; count--;

printk(KERN_INFO \

\

get_task_comm(comm, current), clone_flags & CLONE_STOPPED);

trace = tracehook_prepare_clone(clone_flags);


操作系统课内报告 内核编译、系统调用和进程同步通信 - 图文.doc 将本文的Word文档下载到电脑
搜索更多关于: 操作系统课内报告 内核编译、系统调用和进程同步通信 - 图文 的文档
相关推荐
相关阅读
× 快捷下载通道(下载后可以自由复制和排版)

开通会员免费下载

开通会员后百万份文档资料免费自由复制和下载,是您最优的选择,赶快来试试吧!

单篇下载:10元 点击下载

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:fanwen365 QQ:370150219