当前位置:文档之家› linux源代码分析实验报告格式

linux源代码分析实验报告格式

linux源代码分析实验报告格式
linux源代码分析实验报告格式

Linux的fork、exec、wait代码的

分析

指导老师:景建笃

组员:王步月

张少恒

完成日期:2005-12-16

一、设计目的

1.通过对Linux的fork、exec、wait代码的分析,了解一个操作系统进程的创建、执行、等待、退出的过程,锻炼学生分析大型软件代码的能力;

2.通过与同组同学的合作,锻炼学生的合作能力。

二、准备知识

由于我们选的是题目二,所以为了明确分工,我们必须明白进程的定义。经过查阅资料,我们得知进程必须具备以下四个要素:

1、有一段程序供其执行。这段程序不一定是进程专有,可以与其他进程共用。

2、有起码的“私有财产”,这就是进程专用的系统堆栈空间

3、有“户口”,这就是在内核中有一个task_struct结构,操作系统称为“进程控制块”。有了这个结构,进程才能成为内核调度的一个基本单位。同时,这个结构又是进程的“财产登记卡”,记录着进程所占用的各项资源。

4、有独立的存储空间,意味着拥有专有的用户空间:进一步,还意味着除前述的系统空间堆栈外,还有其专用的用户空间堆栈。系统为每个进程分配了一个task_struct结构,实际分配了两个连续的物理页面(共8192字节),其图如下:

大约1K)

系统空间堆栈 (大约7KB )

对这些基本的知识有了初步了解之后,我们按老师的建议,商量分工。如下: 四、 小组成员以及任务分配

1、王步月:分析进程的创建函数fork.c ,其中包含了get_pid 和do_fork get_pid,写出代码分析结果,并画出流程图来表示相关函数之间的相互调用关系。所占工作比例35%。

2、张少恒:分析进程的执行函数exec.c,其中包含了do_execve 。写出代码分析结果,并画出流程图来表示相关函数之间的相互调用关系。所占工作比例35% 。

3、余波:分析进程的退出函数exit.c,其中包含了do_exit 、sys_wait4。写出代码分析结果,并画出流程图来表示相关函数之间的相互调用关系。所占工作比例30% 。

五、各模块分析: 1、fork.c 一)、概述

进程大多数是由FORK 系统调用创建的.fork 能满足非常高效的生灭机制.除了0进程等少数一,两个进程外,几乎所有的进程都是被另一个进程执行fork 系统调用创建的.调用fork 的进程是父进程,由fork 创建的程是子进程.每个进程都有一个父进程.而一个进程可以有多个子进程.父进程创建一个子进程完成一定的工作时,往往希望子进程结束后,还要把控制权交给父进程,因此子进程不应把父进程覆盖掉.fork 系统调用创建子进程的做法,是把自己复制给子进程,也就是说,新创建的子进程是父进程的一个副本.继而子进程通过exec 系统调用,用一个新的程序来覆盖子进程的内存空间,从而执行那个新程序.系统调用exit 可以终止一个进程的执行,子进程也常常用exit 系统调用来自我终止.子进程终止之后,进入僵死(zombie)状态,父进程可通过执行wait 系统调用来实现与子进程的终止同步,接受子进程的返回状态和返回参数.

二)、代码分析

int do_fork(unsigned long clone_flags, unsigned long stack_start,

struct pt_regs *regs, unsigned long stack_size)

{

int retval;

unsigned long flags;

struct task_struct *p;

struct completion vfork;

if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))

return -EINVAL;

retval = -EPERM;/* 将retval赋值-ENOMEM,作为task_struct结构申请失败时的返回值*/

if (clone_flags & CLONE_PID) {/* 若clone_flags的位是置位的*/

/* 若调用do_fork的当前(父)进程不是idle进程(其pid=0)*/

if (current->pid)

goto fork_out;

}

retval = -ENOMEM;/*返回错误信息*/

p = alloc_task_struct(); /* 申请一个新的task_struct结构*/

if (!p)

goto fork_out;

*p = *current;/* 将当前(父)进程task_struct结构值赋给新创建的(子)进程*/ p->tux_info = NULL;

p->cpus_allowed_mask &= p->cpus_allowed;

retval = -EAGAIN;

/* 若子(新)进程所属的用户拥有的进程数已达到规定的限制值,

* 则跳转至bad_fork_fre */?

if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur && !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE))

goto bad_fork_free;

/* user->__count增一,user->processes(用户拥有的进程数)增一*/ atomic_inc(&p->user->__count);

atomic_inc(&p->user->processes);

/* 若系统进程数超过最大进程数则跳转至bad_fork_cleanup_count */

if (nr_threads >= max_threads)

goto bad_fork_cleanup_count;

get_exec_domain(p->exec_domain);/* 若正在执行的代码是符合iBCS2标准的程序,则增加相对应模块的引用数目*/

/* 若正在执行的代码属于全局执行文件结构格式则增加相对应模块的引用数目*/ if (p->binfmt && p->binfmt->module)

__MOD_INC_USE_COUNT(p->binfmt->module);

p->did_exec = 0;/* 将子进程标志为尚未执行*/

p->swappable = 0; /* 清标志,使内存页面不可换出*/

p->state = TASK_UNINTERRUPTIBLE;/* 将子进程的状态置为uninterruptible */

copy_flags(clone_flags, p);/* 将clone_flags略加修改写入p->flags */

p->pid = get_pid(clone_flags);/* 调用kernel/fork.c:get_pid()为子进程分配一个pid. 若是clone系统调用且

* clone_flags中CLONE_PID位为1,那么父子进程共享一个pid号;否则要分配给子进

* 程一个从未用过的pid */

if (p->pid == 0 && current->pid != 0)

goto bad_fork_cleanup;

/* 对运行队列接口初始化*/

INIT_LIST_HEAD(&p->run_list);

p->p_cptr = NULL;

init_waitqueue_head(&p->wait_chldexit);/* 初始化wait_chldexit等待队列wait_chldexit用于在进程结束时,或发出

* 系统调用wait4后,为了等待子进程结束,而将自己(父进程)睡眠在该队列上*/ p->vfork_done = NULL;

if (clone_flags & CLONE_VFORK) {

p->vfork_done = &vfork;

init_completion(&vfork);

}

spin_lock_init(&p->alloc_lock);

p->sigpending = 0;

init_sigpending(&p->pending);

p->it_real_value = p->it_virt_value = p->it_prof_value = 0;

p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0;

init_timer(&p->real_timer);

p->real_timer.data = (unsigned long) p;

p->leader = 0; /* session leadership doesn't inherit */

p->tty_old_pgrp = 0;

p->times.tms_utime = p->times.tms_stime = 0;

p->times.tms_cutime = p->times.tms_cstime = 0;

#ifdef CONFIG_SMP

{

int i;

/* ?? should we just memset this ?? */

for(i = 0; i < smp_num_cpus; i++)

p->per_cpu_utime[cpu_logical_map(i)] =

p->per_cpu_stime[cpu_logical_map(i)] = 0;

spin_lock_init(&p->sigmask_lock);

}

#endif

p->array = NULL;

p->lock_depth = -1; /* -1 = 没有锁*/

p->start_time = jiffies_64;/* 将当前的jiffies值作为子进程的创建时间*/

/* task_struct结构初始化完毕*/

retval = -ENOMEM;

/* copy all the process information */

if (copy_files(clone_flags, p))/* 复制所有的进程信息,根据clone_flags复制或共享父进程的打开文件表*/

goto bad_fork_cleanup;

if (copy_fs(clone_flags, p))/* 根据clone_flags复制或共享父进程的系统信息*/

goto bad_fork_cleanup_files;

if (copy_sighand(clone_flags, p))/* 根据clone_flags复制或共享父进程的信号处理句柄*/

goto bad_fork_cleanup_fs;

if (copy_mm(clone_flags, p))/* 根据clone_flags复制或共享父进程的存储管理信息*/

goto bad_fork_cleanup_sighand;

if (copy_namespace(clone_flags, p))/* 为子进程复制父进程系统空间堆栈*/ goto bad_fork_cleanup_mm;/* 若系统空间堆栈复制失败跳转至bad_fork_cleanup_mm */

retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);

if (retval)

goto bad_fork_cleanup_namespace;

p->semundo = NULL;

/* 将子进程task_struct结构的self_exec_id赋给parent_exec_id */ p->parent_exec_id = p->self_exec_id;

p->swappable = 1;/* 新进程已经完成初始化,可以换出内存,所以将p->swappable赋1 */

p->exit_signal = clone_flags & CSIGNAL;/* 设置系统强行退出时发出的信号*/

p->pdeath_signal = 0;/* 设置p->pdeath_signal */

/* * Share the timeslice between parent and child, thus the

* total amount of pending timeslices in the system doesnt change,

* resulting in more scheduling fairness.*/

__save_flags(flags);

__cli();

if (!current->time_slice)/* 将父进程的时间片减半*/

BUG();

p->time_slice = (current->time_slice + 1) >> 1;

p->first_time_slice = 1;

current->time_slice >>= 1;

p->sleep_timestamp = jiffies;

if (!current->time_slice) {

current->time_slice = 1;

scheduler_tick(0,0);

}

__restore_flags(flags);

retval = p->pid;/* 如果一切顺利,将子进程的pid作为返回值*/

p->tgid = retval;

INIT_LIST_HEAD(&p->thread_group);

/* Need tasklist lock for parent etc handling! */

write_lock_irq(&tasklist_lock);/* 给进程队列加锁*/

/* CLONE_PARENT re-uses the old parent */

p->p_opptr = current->p_opptr;

p->p_pptr = current->p_pptr;

if (!(clone_flags & CLONE_PARENT)) {

p->p_opptr = current;

if (!(p->ptrace & PT_PTRACED))

p->p_pptr = current;

}

if (clone_flags & CLONE_THREAD) {

p->tgid = current->tgid;

list_add(&p->thread_group, ¤t->thread_group);

}

SET_LINKS(p);/* 将子进程的task_struct结构链入进程队列*/

hash_pid(p);/* 将子进程的task_struct结构链入进程hash表*/

nr_threads++;/* 系统进程计数递增一*/

write_unlock_irq(&tasklist_lock);/* 解除对进程队列的封锁*/

if (p->ptrace & PT_PTRACED)

send_sig(SIGSTOP, p, 1);

wake_up_forked_process(p); /* 最后做这件事,唤醒子进程*/

++total_forks;/* total_forks增一*/

if (clone_flags & CLONE_VFORK)

wait_for_completion(&vfork);

else

current->need_resched = 1;

fork_out:/* 若是vfork()调用do_fork,发down信号*/

return retval;/* 退出do_fork(),返回retval值*/

bad_fork_cleanup_namespace:

exit_namespace(p);

bad_fork_cleanup_mm:

exit_mm(p);

bad_fork_cleanup_sighand:/* 处理子进程task_struct结构与信号处理相关的数据成员, 并删除信号队列中与子进程相

* 关的信号量*/

exit_sighand(p);

bad_fork_cleanup_fs:/* 处理子进程task_struct结构与文件系统信息相关的数据成员*/

exit_fs(p); /* blocking */

bad_fork_cleanup_files:/* 处理子进程task_struct结构与打开文件表相关的数据成员, 并释放子进程的files_struct

* 结构*/

exit_files(p); /* blocking */

bad_fork_cleanup:/* 若正在执行的代码是符合iBCS2标准的程序,则减少相对应模块的引用数目*/

put_exec_domain(p->exec_domain);

if (p->binfmt && p->binfmt->module)

__MOD_DEC_USE_COUNT(p->binfmt->module);

bad_fork_cleanup_count:/* 若正在执行的代码属于全局执行文件结构格式则减少相对应模块的引用数目*/

atomic_dec(&p->user->processes);

free_uid(p->user);/* 清除子进程在user队列中的信息*/

bad_fork_free:

free_task_struct(p);/* 释放子进程的task_struct结构*/

goto fork_out;

}

三)、程序框图如下:

2、exec.c

一)、概述

进程通常是由父进程复制出来的(由fork()或clone())。假若子进程只是父进程的“影子”,那么没有什么意义了。所以,执行一个新的可执行程序才是创建进程的意义所在。在Linux中,提供了一个系统调用execve(),其内核入口是sys_execve()。

二)、代码分析

asmlinkage int sys_execve(struct pt_regs regs )

{

int error;

char *filename;

filename=getname((char*)regs.ebx);

error=PTR_ERR(filename);

if(IS_ERR(filename))

goto out;

error=do_execve(filename,(char**)regs.ecx,(char** )regs.edx,®s);

if(error==0)

current->ptrace &= ~PT_DTRACE;

putname(filename);

out:

return error;

}

regs.ebx中的内容为应用程序中调用相应库函数时的第一个参数。getname()把regs.ebx所指向的字符串从用户空间拷贝到系统空间,在系统空间建立起一个副本。getname()通过dogetname()从用户空间拷贝字符串。

建立起一个可执行文件路径名的副本后,sys_execve()调用do_execve()以完成其主体部分的工作。

int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs) {

struct linux_binprm bprm;

//用于组织运行可执行文件所需的信息,通过此变量与负责处理其部分工作的其他//函数通信;在do_execve返回时废弃;

struct file *file;

int retval;

int i;

file = open_exec(filename); //找到给定的可执行文件并打开;

retval = PTR_ERR(file);

if (IS_ERR(file))

return retval; //检测打开文件是否有错;

首先将给定路径名的可执行文件找到并打开,因而调用open_exec()来实现。函数返回一个file结构指针,代表读入可执行文件的上下文,保存在变量bprm 中。代码开始定义了一个linux_binprm结构的变量bprm,用于将运行一个可执行文件所需的信息组织在一起。linux_binprm结构定义(在include/linux/binfmts.h 中)如下:

struct linux_binprm{

char buf[BINPRM_BUF_SIZE];

struct page *page[MAX_ARG_PAGES];

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

int sh_bang;

struct file * file;

int e_uid, e_gid;

kernel_cap_t cap_inheritable, cap_permitted, cap_effective;

int argc, envc;

char * filename; /* Name of binary */

unsigned long loader, exec;

};

在do_execve()中,接下来的代码是:

bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);//初始化bprm结构的128k页表除去第一个argv[0]);

memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0]));

//将参数页面指针数组初始化为零;

bprm.file = file; //可执行文件的上下文;

bprm.filename = filename; //可执行文件的路径名;

bprm.sh_bang = 0; //可执行文件的性质;

bprm.loader = 0;

bprm.exec = 0;

if ((bprm.argc = count(argv, bprm.p / sizeof(void *))) < 0) {

allow_write_access(file);

fput(file);

return bprm.argc;

} //根据argv数组计算非空指针个数并赋给argc成员;

if ((bprm.envc = count(envp, bprm.p / sizeof(void *))) < 0) {

allow_write_access(file);

fput(file);

return bprm.envc;

} //统计环境变量个数并且赋值给envc的各个成员;

retval = prepare_binprm(&bprm); ////进行访问权限等内容的安全检测后,读入可执行文件前128字节;

if (retval < 0)

goto out;

变量bprm.sh_bang表示可执行文件的性质,此时初始化为0。其他两个变量也设置为0,因为现在还不知道文件性质。Bprm中定义了一个参数页面指针数组,通过memset()将此数组全设置为0;将bprm.p设置为这些页面的总和减去一个指针的大小,原因是argv[0]是可执行文件的路径名。函数count()对用户空间作为参数传过来的字符串指针数组argv[]和环境变量envp[]进行计数。

完成计数后,do_execve()调用prepare_binprm()对bprm中的其他成员准备信息。可执行文件的开头128个字节包含了文件属性的一些重要信息,并将这128个信息读入到bprm的缓冲区中。

retval = copy_strings_kernel(1, &bprm.filename, &bprm); //从系统空间中拷贝可执行文件路径名;

if (retval < 0)

goto out;

bprm.exec = bprm.p;

retval = copy_strings(bprm.envc, envp, &bprm); //从用户空间拷贝环境信息;

if (retval < 0)

goto out;

retval = copy_strings(bprm.argc, argv, &bprm); //从用户空间拷贝参数信息;

if (retval < 0)

goto out;

由于可执行文件的路径名已经在系统空间中了,所以调用copy_strings_kernel ()拷贝到bprm中;其他的argv[]和envp[]还存在于用户空间,调用copy_strings()拷贝到bprm中。

至此,可执行文件运行所需的所有信息都已组织到变量bprm中了,接下来的代码就是装入并运行了。

retval = search_binary_handler(&bprm,regs); //从formats中搜索能够识别的二进制处理程序并将其装入内核,以便执行;

if (retval >= 0) //找到能够识别的二进制处理程序;

/* execve success */

return retval;

out:

/* Something went wrong, return the inode and free the argument pages*/ allow_write_access(bprm.file);

if (bprm.file)

fput(bprm.file);

for (i = 0 ; i < MAX_ARG_PAGES ; i++) {

struct page * page = bprm.page[i];

if (page)

__free_page(page); //释放为参数和环境所分配的物理页面,并返回一个负数通知调用者调用失败;

}

return retval;

}

在此段代码中,最重要的的是函数search_binary_handler(),其中有两个for()循环。内层循环是每个formats队列(每个成员是认识并处理唯一一种文件格式的二进制处理程序)成员的循环,让每个成员调用自己的load_binary()去识别;若能识别则装入可执行文件并运行,返回一个正数或零;不能则返回一个负数。内层寻常结束后,如果返回的负数是

-ENOEXEC,表示所有的formats成员都不能识别此文件格式。如果内核支持动态安装模块,就根据目标文件的第2、3个字节生成一个binfmt模块名,通过request_module()试着将模块装入,以便外层for()循环在装入模块后再来一次内层循环。

三)、程序框图如下:

3、exit.c

一)、概述

Exit.c中核心是do-exit(),cpu不会从do-exit()返回,中断服务程序不调用do-exit,in-interrupt()对此加以检查.因此在分析程序时,先浏览整段代码,然后开始分析do-exit()函数.在这个主函数中涉及到几个函数的调用,分别对这些函数进行分析,分析每个函数的功能和作用.

进程在结束退出前要释放所有系统资源.比如存储空间,已打开文件,工作目录,信号处理表等是通过函数_exit_mm(), _exit_files(),_exit_fs(),_exit_sighand()来完成的. _exit_mm()存储空间的释放,调用mm_release()唤醒睡眠中的父进程,当前进程状态改成TASK_ZOMBIE,调用exit-notify(),通知父进程子进程已退出.cpu完成exit-notify()后,回到do-exit(),调用schedule().

Sys_wait4()函数中,参数pid为某一子进程的进程号,此函数的作用是等待子进程变成TASK_ZOMBIE.task-struct结构一开始就在当前进程的系统堆栈分配一个等待队列. 当task-struct结构释放后,子进程就结束.在这个过程中,父进程正在wait4中等待.unhash_process()把子进程删除,把子进程的其他统计信息也合并入父进程.然后就调用task_release()释放子进程残存的资源.

二)、代码分析

NORET_TYPE void do_exit(long code)//将退出代码作为参数处理,在其类型前用到特殊符号NORET_TYPE

{

struct task_struct *tsk = current;

if (in_interrupt())

panic("Aiee, killing interrupt handler!");

if (!tsk->pid)

panic("Attempted to kill the idle task!");

if (tsk->pid == 1)

panic("Attempted to kill init!");

tsk->flags |= PF_EXITING;

del_timer_sync(&tsk->real_timer);

fake_volatile:

#ifdef CONFIG_BSD_PROCESS_ACCT

acct_process(code);

#endif

if (current->tux_info) {

#ifdef CONFIG_TUX_DEBUG

printk("Possibly unexpected TUX-thread exit(%ld) at %p?\n",

code, __builtin_return_address(0));

#endif

current->tux_exit();

}

__exit_mm(tsk);//释放分配给它的内存

lock_kernel();

sem_exit();//释放信号量和其他system VIPC结构

__exit_files(tsk);//释放分配给它的文件

__exit_fs(tsk);//释放文件系统的数据

exit_namespace(tsk);

exit_sighand(tsk);//释放信号量处理程序表

exit_thread();

if (current->leader)

disassociate_ctty(1);

put_exec_domain(tsk->exec_domain);

if (tsk->binfmt && tsk->binfmt->module)

__MOD_DEC_USE_COUNT(tsk->binfmt->module);

tsk->exit_code = code;

exit_notify();//调用exit_notify,它会警告当前退出任务的祖先进程和其进程组中的所有成员该进程正在退出

schedule();/*调用schedule(),释放CPU,这对schedule()

的调用从来不返回因为它跳转到下一个进程的上下文,

不会再跳转回来,这是现在正在退出的进程最后一次

拥有CPU的机会*/

BUG();

asmlinkage long sys_exit(int error_code)

{

do_exit((error_code&0xff)<<8);

}

asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru)/*sys_wait4有很多参数。pid是目标进程的PID.O和负值是特殊情况如果stat_addr非空,它就是所得子孙进程的退出状态应该拷贝到的地址

options是一些可能定义sys-wait4的操作的标志的集合。如果ru非空,

那么它就是所得子孙进程资源使用信息应该拷贝到的地址*/

{

int flag, retval;

DECLARE_WAITQUEUE(wait, current);

struct task_struct *tsk;

if (options & ~(WNOHANG|WUNTRACED|__WNOTHREAD|__WCLONE|__WALL))//如果提供了无效选项sys_wait4就返回错误代码

return -EINVAL;

add_wait_queue(¤t->wait_chldexit,&wait);//增加到等待队列中

repeat:

flag = 0;

current->state = TASK_INTERRUPTIBLE;

read_lock(&tasklist_lock);

tsk = current;

do {

struct task_struct *p;

for (p = tsk->p_cptr ; p ; p = p->p_osptr)//循环遍历该进程的直接子进程

{

if (pid>0) {//根据pid参数的值筛选出不匹配的PID

if (p->pid != pid)

continue;

} else if (!pid) {

if (p->pgrp != current->pgrp)

continue;

} else if (pid != -1) {

if (p->pgrp != -pid)

continue;

}

if (((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0))

&& !(options & __WALL))

continue;

flag = 1;

switch (p->state) {

case TASK_STOPPED:

if (!p->exit_code)

continue;

if (!(options & WUNTRACED) && !(p->ptrace & PT_PTRACED))

continue;

read_unlock(&tasklist_lock);

retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;

if (!retval && stat_addr)

retval = put_user((p->exit_code << 8) | 0x7f, stat_addr);

if (!retval) {

p->exit_code = 0;

retval = p->pid;

}

goto end_wait4;

case TASK_ZOMBIE://祖先进程正在等待一个已经结束了的进程

current->times.tms_cutime += p->times.tms_utime + p->times.tms_cutime;

current->times.tms_cstime += p->times.tms_stime + p->times.tms_cstime;

read_unlock(&tasklist_lock);

retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;/*其他的资源使用信息被收集起来,子孙进程的退出状态被传递到特定的地址

中*/

if (!retval && stat_addr)

retval = put_user(p->exit_code, stat_addr);

if (retval)

goto end_wait4;

retval = p->pid;//设置retval为当前得到的死亡子孙进程的PID;retval不会在

改变

if (p->p_opptr != p->p_pptr) {/*如果这个垂死进程的当前祖先进程不是原来的祖先进程,进程就会离开进程图表中的当前位置,在其原始祖先的控制下,重

新安装自己,接着给其祖先进程发送SIGCHLD信号量,这样祖先进程就

知道其子孙进程已推出*/

write_lock_irq(&tasklist_lock);

REMOVE_LINKS(p);

p->p_pptr = p->p_opptr;

SET_LINKS(p);

do_notify_parent(p, SIGCHLD);

write_unlock_irq(&tasklist_lock);

linux实验报告

实验一 实验名称:Linux 基本命令的使用 实验时间:2学时 实验目的:熟练使用Linux字符界面、窗口系统的常用命令。 实验内容 (一)Linux操作基础 1.重新启动linux或关机(poweroff,shutdown,reboot,init 0,init 6) 2.显示系统信息(uname),显示系统日期与时间,查看2014年日历(date,cal) ①uname:查看系统与内核相关信息 uname -asrmpi 参数: -a :所有系统相关的信息; -s: 系统内核名称; -r: 内核的版本; -m:本系统的硬件名称,如i686或x86_64; -p: CPU的类型,与-m类似,只是显示的是CPU的类型; -i :硬件的平台(ix86). ②date:显示日期的命令 ③cal:显示日历 单独cal:列出当前月份的日历 cal 2014:列出2014年的日历 cal 5 2014:列出2014年五月的目录 3.使用帮助命令(man,help) ①man:是manual(操作说明)的简写,是在线帮助系统 man后跟某个命令就会详细说明此命令,例如:man man就会详细说明man 这个命令的用法; ②help:也是帮助命令,一般会在命令后,例如:cd --help 就会列出cd命令的使用说明。 4.查看当前登陆用户列表(who),显示当前用户(whoami) ①who:显示目前已登录在系统上面的用户信息; ②whoami:查询当前系统账户 5.建立一个新用户mytest,设定密码(useradd,passwd) ①useradd mytest(建立新用户mytest);

LINUX实验报告

实验报告 ( 2014/ 2015 学年第一学期) 课程名称操作系统A 实验名称文件系统 实验时间2014 年12 月8 日指导单位计算机学院计算机科学与技术系 指导教师徐鹤 学生姓名王生荣班级学号B12040809 学院(系) 计算机学院专业软件工程

实验名称文件系统指导教师徐鹤 实验类型设计实验学时 2 实验时间2014.12.08 一、实验目的和要求 1. 学习LINUX系统下对文件进行操作的各种命令和图形化界面的使用方法。 2. 深入学习和掌握文件管理系统的基本原理和LINUX等操作系统下常用的系统调用,编写一个使用系统调用的例程。 3.实现一个文本文件的某信息的插入和删除 4.实现一个记录文件的某记录的插入和删除 二、实验环境(实验设备) Windows XP + VMWare + RedHat Linux 8

三、实验过程描述与结果分析 1. 目录/proc下与系统相关的文件和目录 (1) /proc/$pid/fd:这是一个目录,该进程($PID号码进程)每个打开的文件在该目录下有一个对应的文件。 例如:#ls /proc/851/fd 0 1 2 255 这表示,851号进程目前正在使用(已经打开的)文件有4个,它们的描述符分别是0、1、2、255。其中,0、1、2 依次分别是进程的标准输入、标准输出和标准错误输出设备。 (2)/proc/filesystems:该文件记录了可用的文件系统类型。 (3)/proc/mounts:该记录了当前被安装的文件系统信息 例如:#cat /proc/mount (4)/proc/$pid/maps:该文件记录了进程的映射内存区信息。 例如:#cat /proc/851/maps 2.常用命令讲解 ls 命令 用来查看用户有执行权限的任意目录中的文件列表,该命令有许多有趣的选项。例如: $ ls -liah * 22684 -rw-r--r-- 1 bluher users 952 Dec 28 18:43 .profile

浙江大学Linux程序设计实验报告

Linux程序设计实验报告1 ——操作系统基本命令使用 一、实验目的 1.通过对Emacs、vi、vim、gedit文本编辑器的使用,掌握在Linux环境下文本文件的编辑方法; 2.通过对常用命令mkdir、cp、cd、ls、mv、chmod、rm等文件命令的操作,掌握Linux操作系统中文件命令的用法。 二、实验任务与要求 1.emacs的使用,要求能新建、编辑、保存一个文本文件 2.vi或vim的使用,要求能新建、编辑、保存一个文本文件 3.gedit的使用,要求能新建、编辑、保存一个文本文件 4.掌握mkdir、cd命令的操作,要求能建立目录、进入与退出目录 5.掌握cp、ls、mv、chmod、rm命令的操作,要求能拷贝文件、新建文件、查看文件、文件重命名、删除文件等操作。 三、实验工具与准备 计算机PC机,Linux Redhat Fedora Core6操作系统 四、实验步骤与操作指导 任务1.学习emacs的使用,要求能新建、编辑、保存一个文本文件 (1)启动emacs (2)输入以下C程序 (3)保存文件为kk.c (4)用emacs打开文件kk.c (5)修改程序 (6)另存为文件aa.txt并退出。 任务2.vi或vim的使用,要求能新建、编辑、保存一个文本文件 (1)点击”应用程序”→ “附件”→“终端”,打开终端,在终端输入命令: [root@localhost root]#vi kk.c 按i键,进入插入状态。 (2)输入以下C程序 #include int main( ) {

printf(“Hello world!\n”); return 0; } 此时可以用Backspace、→、←、↑、↓键编辑文本。 (3)保存文件为kk.c 按Esc键,进入最后行状态,在最后行状态输入:wq保存文件,退出vi。 (4)用vi打开文件kk.c,输入命令: [root@localhost root]#vi kk.c (5)修改程序为: #include int main( ) { printf(" Hello world!\n"); printf("*****************\n"); return 0; } (6)按Esc键,进入最后行状态,在最后行状态输入:wq aa.txt保存文件,如图1所示,另存为文件aa.txt并退出vi。。 图1 程序编辑环境 任务3.gedit的使用,要求能新建、编辑、保存一个文本文件 (1)启动gedit,点击”应用程序”→ “附件”→“文本编辑器”,打开文本编辑器,如图所示。

Linux操作系统源代码详细分析

linux源代码分析:Linux操作系统源代码详细分析 疯狂代码 https://www.doczj.com/doc/e29872553.html,/ ?:http:/https://www.doczj.com/doc/e29872553.html,/Linux/Article28378.html 内容介绍: Linux 拥有现代操作系统所有功能如真正抢先式多任务处理、支持多用户内存保护虚拟内存支持SMP、UP符合POSIX标准联网、图形用户接口和桌面环境具有快速性、稳定性等特点本书通过分析Linux内核源代码充分揭示了Linux作为操作系统内核是如何完成保证系统正常运行、协调多个并发进程、管理内存等工作现实中能让人自由获取系统源代码并不多通过本书学习将大大有助于读者编写自己新 第部分 Linux 内核源代码 arch/i386/kernel/entry.S 2 arch/i386/kernel/init_task.c 8 arch/i386/kernel/irq.c 8 arch/i386/kernel/irq.h 19 arch/i386/kernel/process.c 22 arch/i386/kernel/signal.c 30 arch/i386/kernel/smp.c 38 arch/i386/kernel/time.c 58 arch/i386/kernel/traps.c 65 arch/i386/lib/delay.c 73 arch/i386/mm/fault.c 74 arch/i386/mm/init.c 76 fs/binfmt-elf.c 82 fs/binfmt_java.c 96 fs/exec.c 98 /asm-generic/smplock.h 107 /asm-i386/atomic.h 108 /asm- i386/current.h 109 /asm-i386/dma.h 109 /asm-i386/elf.h 113 /asm-i386/hardirq.h 114 /asm- i386/page.h 114 /asm-i386/pgtable.h 115 /asm-i386/ptrace.h 122 /asm-i386/semaphore.h 123 /asm-i386/shmparam.h 124 /asm-i386/sigcontext.h 125 /asm-i386/siginfo.h 125 /asm-i386/signal.h 127 /asm-i386/smp.h 130 /asm-i386/softirq.h 132 /asm-i386/spinlock.h 133 /asm-i386/system.h 137 /asm-i386/uaccess.h 139 //binfmts.h 146 //capability.h 147 /linux/elf.h 150 /linux/elfcore.h 156 /linux/errupt.h 157 /linux/kernel.h 158 /linux/kernel_stat.h 159 /linux/limits.h 160 /linux/mm.h 160 /linux/module.h 164 /linux/msg.h 168 /linux/personality.h 169 /linux/reboot.h 169 /linux/resource.h 170 /linux/sched.h 171 /linux/sem.h 179 /linux/shm.h 180 /linux/signal.h 181 /linux/slab.h 184 /linux/smp.h 184 /linux/smp_lock.h 185 /linux/swap.h 185 /linux/swapctl.h 187 /linux/sysctl.h 188 /linux/tasks.h 194 /linux/time.h 194 /linux/timer.h 195 /linux/times.h 196 /linux/tqueue.h 196 /linux/wait.h 198 init/.c 198 init/version.c 212 ipc/msg.c 213 ipc/sem.c 218 ipc/shm.c 227 ipc/util.c 236 kernel/capability.c 237 kernel/dma.c 240 kernel/exec_do.c 241 kernel/exit.c 242 kernel/fork.c 248 kernel/info.c 255 kernel/itimer.c 255 kernel/kmod.c 257 kernel/module.c 259 kernel/panic.c 270 kernel/prk.c 271 kernel/sched.c 275 kernel/signal.c 295 kernel/softirq.c 307 kernel/sys.c 307 kernel/sysctl.c 318 kernel/time.c 330 mm/memory.c 335 mm/mlock.c 345 mm/mmap.c 348 mm/mprotect.c 358 mm/mremap.c 361 mm/page_alloc.c 363 mm/page_io.c 368 mm/slab.c 372 mm/swap.c 394 mm/swap_state.c 395 mm/swapfile.c 398 mm/vmalloc.c 406 mm/vmscan.c 409

2《Linux基础》实验报告 基本配置Linux

实验序号: 2 《Linux基础》 实验报告 实验名称:基本配置Linux操作系统 姓名: 学院:计算机学院 专业: 班级: 学号: 指导教师: 实验地址:N6-113 实验日期:2017.3.7

说明 一.排版要求 1.实验报告“文件名”按模板要求填写。 2.一级标题:顶格排版。汉字用宋体,阿拉伯数字用Times New Roman字 体,四号字体,加粗。 3.二级标题:顶格排版。汉字用宋体,阿拉伯数字用Times New Roman字 体,小四号字体,加粗。 4.三级标题:顶格排版。汉字用宋体,阿拉伯数字用Times New Roman字 体,五号字体。 5.正文:每段缩进量:2个汉字。两端对齐;汉字用宋体,阿拉伯数字用 Times New Roman字体,五号字体。 6.图形要求 (1)在正文中要有引用。 (2)要有图名,图名位于图的下方,汉字用宋体,阿拉伯数字用Times New Roman字体,五号字体。 (3)图和图名“居中”。 7.表格要求 (1)在正文中要有引用。 (2)要有表名,表名位于表的上方,汉字用宋体,阿拉伯数字用Times New Roman字体,五号字体。 (3)表和表名“居中”。 二.注意事项 1.复制、拷贝、抄袭者取消成绩。 2.没有安实验报告排版要求者不及格。

实验2基本配置Linux操作系统实验 【实验目的】 1.。。。。 2.。。。。 3.。。。。 4.思考: (1)Linux默认的系统超级管理员帐户是什么? (2)Linux的操作系统引导器是什么?它有哪几种的操作界面? (3)RHEL的支持哪几种X-Window图形管理器?默认是使用哪一种?(4)RHEL支持哪几种Shell?默认是使用哪一种? 【实验原理】 1.。。。 。。。 2.。。。 。。。 (1)。。。 。。。 (2)。。。 。。。 3.。。 【实验环境】 1.实验配置 本实验所需的软硬件配置如表1所示。 表1 实验配置 本实验的环境如图1所示。

linux内核IMQ源码实现分析

本文档的Copyleft归wwwlkk所有,使用GPL发布,可以自由拷贝、转载,转载时请保持文档的完整性,严禁用于任何商业用途。 E-mail: wwwlkk@https://www.doczj.com/doc/e29872553.html, 来源: https://www.doczj.com/doc/e29872553.html,/?business&aid=6&un=wwwlkk#7 linux2.6.35内核IMQ源码实现分析 (1)数据包截留并重新注入协议栈技术 (1) (2)及时处理数据包技术 (2) (3)IMQ设备数据包重新注入协议栈流程 (4) (4)IMQ截留数据包流程 (4) (5)IMQ在软中断中及时将数据包重新注入协议栈 (7) (6)结束语 (9) 前言:IMQ用于入口流量整形和全局的流量控制,IMQ的配置是很简单的,但很少人分析过IMQ的内核实现,网络上也没有IMQ的源码分析文档,为了搞清楚IMQ的性能,稳定性,以及借鉴IMQ的技术,本文分析了IMQ的内核实现机制。 首先揭示IMQ的核心技术: 1.如何从协议栈中截留数据包,并能把数据包重新注入协议栈。 2.如何做到及时的将数据包重新注入协议栈。 实际上linux的标准内核已经解决了以上2个技术难点,第1个技术可以在NF_QUEUE机制中看到,第二个技术可以在发包软中断中看到。下面先介绍这2个技术。 (1)数据包截留并重新注入协议栈技术

(2)及时处理数据包技术 QoS有个技术难点:将数据包入队,然后发送队列中合适的数据包,那么如何做到队列中的数

激活状态的队列是否能保证队列中的数据包被及时的发送吗?接下来看一下,激活状态的队列的 证了数据包会被及时的发送。 这是linux内核发送软中断的机制,IMQ就是利用了这个机制,不同点在于:正常的发送队列是将数据包发送给网卡驱动,而IMQ队列是将数据包发送给okfn函数。

linux操作系统实验报告要点

LINUX操作系统实验报告 姓名 班级学号 指导教师 2011 年05月16 日 实验一在LINUX下获取帮助、Shell实用功能 实验目的: 1、掌握字符界面下关机及重启的命令。 2、掌握LINUX下获取帮助信息的命令:man、help。 3、掌握LINUX中Shell的实用功能,命令行自动补全,命令历史记录,命令的排列、替

换与别名,管道及输入输出重定向。 实验内容: 1、使用shutdown命令设定在30分钟之后关闭计算机。 2、使用命令“cat /etc/cron.daliy”设置为别名named,然后再取消别名。 3、使用echo命令和输出重定向创建文本文件/root/nn,内容是hello,然后再使用追加重定向输入内容为word。 4、使用管道方式分页显示/var目录下的内容。 5、使用cat显示文件/etc/passwd和/etc/shadow,只有正确显示第一个文件时才显示第二个文件。 实验步骤及结果: 1.用shutdown命令安全关闭系统,先开机在图形界面中右击鼠标选中新建终端选项中输入 命令Shutdown -h 30 2、使用命令alias将/etc/cron.daliy文件设置为别名named,左边是要设置的名称右边是要更改的文件。查看目录下的内容,只要在终端输入命令即可。取消更改的名称用命令unalias 命令:在命令后输入要取消的名称,再输入名称。 3.输入命令将文件内容HELLO重定向创建文本文件/root/nn,然后用然后再使用追加重定向输入内容为word。步骤与输入内容HELLO一样,然后用命令显示文件的全部内容。 4.使用命令ls /etc显示/etc目录下的内容,命令是分页显示。“|”是管道符号,它可以将多个命令输出信息当作某个命令的输入。

读Linux内核源代码

Linux内核分析方法 Linux的最大的好处之一就是它的源码公开。同时,公开的核心源码也吸引着无数的电脑爱好者和程序员;他们把解读和分析Linux的核心源码作为自己的最大兴趣,把修改Linux源码和改造Linux系统作为自己对计算机技术追求的最大目标。 Linux内核源码是很具吸引力的,特别是当你弄懂了一个分析了好久都没搞懂的问题;或者是被你修改过了的内核,顺利通过编译,一切运行正常的时候。那种成就感真是油然而生!而且,对内核的分析,除了出自对技术的狂热追求之外,这种令人生畏的劳动所带来的回报也是非常令人着迷的,这也正是它拥有众多追随者的主要原因: ?首先,你可以从中学到很多的计算机的底层知识,如后面将讲到的系统的引导和硬件提供的中断机制等;其它,象虚拟存储的实现机制,多任务机制,系统保护机制等等,这些都是非都源码不能体会的。 ?同时,你还将从操作系统的整体结构中,体会整体设计在软件设计中的份量和作用,以及一些宏观设计的方法和技巧:Linux的内核为上层应用提供一个与具体硬件不相关的平台; 同时在内核内部,它又把代码分为与体系结构和硬件相关的部分,和可移植的部分;再例如,Linux虽然不是微内核的,但他把大部分的设备驱动处理成相对独立的内核模块,这样减小了内核运行的开销,增强了内核代码的模块独立性。 ?而且你还能从对内核源码的分析中,体会到它在解决某个具体细节问题时,方法的巧妙:如后面将分析到了的Linux通过Botoom_half机制来加快系统对中断的处理。 ?最重要的是:在源码的分析过程中,你将会被一点一点地、潜移默化地专业化。一个专业的程序员,总是把代码的清晰性,兼容性,可移植性放在很重要的位置。他们总是通过定义大量的宏,来增强代码的清晰度和可读性,而又不增加编译后的代码长度和代码的运行效率; 他们总是在编码的同时,就考虑到了以后的代码维护和升级。甚至,只要分析百分之一的代码后,你就会深刻地体会到,什么样的代码才是一个专业的程序员写的,什么样的代码是一个业余爱好者写的。而这一点是任何没有真正分析过标准代码的人都无法体会到的。 然而,由于内核代码的冗长,和内核体系结构的庞杂,所以分析内核也是一个很艰难,很需要毅力的事;在缺乏指导和交流的情况下,尤其如此。只有方法正确,才能事半功倍。正是基于这种考虑,作者希望通过此文能给大家一些借鉴和启迪。 由于本人所进行的分析都是基于2.2.5版本的内核;所以,如果没有特别说明,以下分析都是基于i386单处理器的2.2.5版本的Linux内核。所有源文件均是相对于目录/usr/src/linux的。 方法之一:从何入手 要分析Linux内核源码,首先必须找到各个模块的位置,也即要弄懂源码的文件组织形式。虽然对于有经验的高手而言,这个不是很难;但对于很多初级的Linux爱好者,和那些对源码分析很

操作系统-Linux课程实验报告材料

实验1.1、1.2 Linux Ubuntu的安装、创建新的虚拟机VMWare

实验1.3 Shell编程 1.实验目的与内容 通过本实验,了解Linux系统的shell机制,掌握简单的shell编程技巧。 编制简单的Shell程序,该程序在用户登录时自动执行,显示某些提示信息,如“Welcome to Linux”, 并在命令提示符中包含当前时间、当前目录和当前用户名等基本信息。 2.程序源代码清单 #include #include int main(){ printf("Hello Linux\n"); int pid; int state; int pfd[2]; pipe(pfd); if (fork()==0){ printf("In the grep progress\n"); dup2(pfd[0],0); close(pfd[0]); close(pfd[1]); execlp("grep","grep","sh",0); perror("exelp grep error");

} esle if(fork()==0){ printf("In the ps progress\n"); dup2(pfd[1],1); close(pfd[0]); close(pfd[1]); execlp("ps","ps","-ef",0); perror("execlp ps -ef"); } close(pfd[1]); close(pfd[0]); wait(&state); wait(&state); } 实验2.3 内核模块 实验步骤: (1).编写内核模块 文件中主要包含init_clock(),exit_clock(),read_clock()三个函数。其中init_clock(),exit_clock()负责将模块从系统中加载或卸载,以及增加或删除模块在/proc中的入口。read_clock()负责产生/proc/clock被读时的动作。(2).编译内核模块Makefile文件 # Makefile under 2.6.25

Linux文件系统实验报告

黄冈师学院 提高型实验报告 实验课题文件系统的设计与实现(实验类型:□综合性 设计性□应用性) 实验课程操作系统原理 实验时间2015-2016 第二学期 学生何正发 专业班级软件工程1401 学号07

成绩: 一、实验目的和要求 1、熟悉操作系统设计的过程,巩固操作系统的基本知识,加深对操作原理、功能及各种不同的存储管理方法理解与应用; 2、学会运用各种语言、软件开发新软件的基本方法; 3、增强实际应用能力和动手操作能力。 二、实验条件 Win7 /Windows 8.1/Linux等操作系统,装有java、C、C++、C#等语言工具的环境。 三、实验原理分析 可以选择最佳适应算法,按照从小到大的次序组成空闲区自由链,当用户作业或进程申请一个空闲区时,存储管理 程序从表头开始查找,当找到第一个満足要求的空闲区时,停止查找。如果该空闲区大于请求表中的请求长 度,将减去请求长度后的剩余空闲区部分留在可用表中。回收时,从作链中删去要回收的作业块,同时在空 闲链中插入该作业大小的空闲区,并按顺序排列 四、实验方案或步骤 1、应用环境、需求分析 本模拟系统主要针对文件的管理和操作名主要有:创建用户、文件、文件夹,读文件,写文件,执行文件,关闭文件,删除用户、文件夹、文件的功能。 创建用户、文件、文件夹:在对系统发出操作命令之前必须先登录用户,然而登录之前必须创建该用户。在创建完后,可通过登录用户来创建文件和文件夹。在创建文件时可设置文件的属性和输入文件的容。 读文件:读取任何已创建的只读或读写文件的容;如果所要读的文件不是可读文件时,系统会显示该文件不可读;如果所读文件不存在,系统会显示文件不存在。 写文件用户可写或重写读写文件中的容,并保存文件中的重写容,以供下次读取;当所要写的文件不是可写的文件时,系统会显示该文件不可写;当所要写的文件并不存在时,系统会显示该文件不存在。

Linux内核源代码阅读与工具介绍

Linux的内核源代码可以从很多途径得到。一般来讲,在安装的linux系统下,/usr/src/linux 目录下的东西就是内核源代码。另外还可以从互连网上下载,解压缩后文件一般也都位于linux目录下。内核源代码有很多版本,目前最新的版本是2.2.14。 许多人对于阅读Linux内核有一种恐惧感,其实大可不必。当然,象Linux内核这样大而复杂的系统代码,阅读起来确实有很多困难,但是也不象想象的那么高不可攀。只要有恒心,困难都是可以克服的。任何事情做起来都需要有方法和工具。正确的方法可以指导工作,良好的工具可以事半功倍。对于Linux内核源代码的阅读也同样如此。下面我就把自己阅读内核源代码的一点经验介绍一下,最后介绍Window平台下的一种阅读工具。 对于源代码的阅读,要想比较顺利,事先最好对源代码的知识背景有一定的了解。对于linux内核源代码来讲,基本要求是:⑴操作系统的基本知识;⑵对C语言比较熟悉,最好要有汇编语言的知识和GNU C对标准C的扩展的知识的了解。另外在阅读之前,还应该知道Linux内核源代码的整体分布情况。我们知道现代的操作系统一般由进程管理、内存管理、文件系统、驱动程序、网络等组成。看一下Linux内核源代码就可看出,各个目录大致对应了这些方面。Linux内核源代码的组成如下(假设相对于linux目录): arch这个子目录包含了此核心源代码所支持的硬件体系结构相关的核心代码。如对于X86平台就是i386。 include这个目录包括了核心的大多数include文件。另外对于每种支持的体系结构分别有一个子目录。 init此目录包含核心启动代码。 mm此目录包含了所有的内存管理代码。与具体硬件体系结构相关的内存管理代码位于arch/*/mm目录下,如对应于X86的就是arch/i386/mm/fault.c。 drivers系统中所有的设备驱动都位于此目录中。它又进一步划分成几类设备驱动,每一种也有对应的子目录,如声卡的驱动对应于drivers/sound。 ipc此目录包含了核心的进程间通讯代码。 modules此目录包含已建好可动态加载的模块。 fs Linux支持的文件系统代码。不同的文件系统有不同的子目录对应,如ext2文件系统对应的就是ext2子目录。 kernel主要核心代码。同时与处理器结构相关代码都放在arch/*/kernel目录下。 net核心的网络部分代码。里面的每个子目录对应于网络的一个方面。 lib此目录包含了核心的库代码。与处理器结构相关库代码被放在arch/*/lib/目录下。

Linux常用命令实验报告

实验二 姓名:陈辉龙学号:201407010201 班级:14计科(1)一.实验目的: 掌握Linux常见命令,为今后的实验打下良好的基础。 二.实验内容 1.新建用户为chenhuilong,配置密码为passwd: 2.切换到chenhuilong用户,并在/home/chenhuilong目录下新建文件夹dir: 3.在文件夹dir下新建文件hello(内容为"printf hello world!"),并将其拷贝至/home/user目录: 4.统计/home/user目录下文件的个数,包括子目录里的首字符为-的普通文件:

5.统计/home下目录的个数,包括子目录里的目录: 6.显示/home/user目录下名为hello的文件的行数、字数以及字符数(使用输入重定向): 7.将上步的结果输出重定向到名为cnt_hello的文件: 8.删除/home/user目录下的hello文件: 9.进入/home/user/dir文件夹,将hello文件属性变为-rwxrw-r--(使用符号标记方式),并为hello文件在/home/user目录下建立软链接,链接文件名为link_hello:

10.查看/home/user/dir/hello文件的详细信息: 11.切换至根目录下查找hello文件: 12.打包home/user/dir/hello文件,并进行压缩,然后再进行解压缩解包: 13.退出user用户,删除/home/user文件夹:

14.将文件夹/home的所有者改为user用户,并删除user用户: 三.实验总结: 本实验旨在熟悉Unix的常用命令,实验较简单,操作起来还算顺利,做了一遍感觉还不是很熟悉,因此做了两遍,第二遍就很得心顺手。通过这次实验,熟悉了一些常用的命令操作,为以后的学习打下坚实的基础,提高自己的动手能力。

linux源代码分析实验报告格式

linux源代码分析实验报告格式

Linux的fork、exec、wait代码的分析 指导老师:景建笃 组员:王步月 张少恒 完成日期:2005-12-16

一、 设计目的 1.通过对Linux 的fork 、exec 、wait 代码的分析,了解一个操作系统进程的创建、 执行、等待、退出的过程,锻炼学生分析大型软件代码的能力; 2.通过与同组同学的合作,锻炼学生的合作能力。 二、准备知识 由于我们选的是题目二,所以为了明确分工,我们必须明白进程的定义。经过 查阅资料,我们得知进程必须具备以下四个要素: 1、有一段程序供其执行。这段程序不一定是进程专有,可以与其他进程共用。 2、有起码的“私有财产”,这就是进程专用的系统堆栈空间 3、有“户口”,这就是在内核中有一个task_struct 结构,操作系统称为“进程控制 块”。有了这个结构,进程才能成为内核调度的一个基本单位。同时,这个结构又 是进程的“财产登记卡”,记录着进程所占用的各项资源。 4、有独立的存储空间,意味着拥有专有的用户空间:进一步,还意味着除前述的 系统空间堆栈外,还有其专用的用户空间堆栈。系统为每个进程分配了一个 task_struct 结构,实际分配了两个连续的物理页面(共8192字节),其图如下: Struct task_struct (大约1K) 系统空间堆栈 (大约7KB )两个 连续 的物 理页 面 对这些基本的知识有了初步了解之后,我们按老师的建议,商量分工。如下: 四、 小组成员以及任务分配 1、王步月:分析进程的创建函数fork.c ,其中包含了get_pid 和do_fork get_pid, 写出代码分析结果,并画出流程图来表示相关函数之间的相互调用关系。所占工作 比例35%。 2、张少恒:分析进程的执行函数exec.c,其中包含了do_execve 。写出代码分析结 果,并画出流程图来表示相关函数之间的相互调用关系。所占工作比例35% 。 3、余波:分析进程的退出函数exit.c,其中包含了do_exit 、sys_wait4。写出代码 分析结果,并画出流程图来表示相关函数之间的相互调用关系。所占工作比例30% 。 五、各模块分析: 1、fork.c 一)、概述 进程大多数是由FORK 系统调用创建的.fork 能满足非常高效的生灭机制.除了 0进程等少数一,两个进程外,几乎所有的进程都是被另一个进程执行fork 系统调 用创建的.调用fork 的进程是父进程,由fork 创建的程是子进程.每个进程都有一

实验一 Linux基本操作实验报告

实验一Linux基本操作 一.实验目的: 1. 二.实验环境: 虚拟机+Red Hat Enterprise Server 5.0 三.实验内容: 根据以下的文字提示,调用相应的命令来完成,记录相应的运行结果。一)用户和组基本操作 1.添加一个user01用户,家目录为/home/sub2,并设置密码 2.添加一个group1 组 3.将user01用户添加到group1组中 4.修改group1组名称为group2 5.修改user01的家目录为/home/user01 6.判断/etc/password这个目录是否包含user01这个用户 7.修改user01的shell为/bin/tcsh 8.添加一个group3组,把user01和root用户都添加到该组

https://www.doczj.com/doc/e29872553.html,er01用户从group2组切换到group3组 10.设置user01的密码在2012-5-20过期 11.把/home/user01目录所属的组修改为group3 12.删除user01帐号 13.查看内核版本号 二)进程管理 1.运行cat命令:vi test,输入若干字符如this is a example,挂起vi进程 2.显示当前所有作业 3.将vi进程调度到前台运行

4.将vi进程调度到后台并分别用kill/pkill/killall命令结束该该进程。 三)磁盘管理 1.通过fdisk 将为硬盘增加一个分区(主分区或者逻辑分区)。 2.并格式化ext3系统,

3.检测分区是否有坏道 4.检测分区的完整性 5.加载分区到/mnt目录(或者其他分区)下,并拷贝一些文件到该目录下 6.(选做)为test用户设置磁盘配额(软限制和硬限制参数自行设定) 7.退出/mnt目录后卸载该分区 8.用du查看/usr目录的大小

linux编程实验报告

linux编程实验报告 篇一:Linux程序设计实验报告 《Linux程序设计》 实验报告 安徽工业大学计算机学院 XX年6月 1 实验一 Linux基本 命令的使用 1、实验目的 学习和掌握Linux的基本命令。 2、实验内容和步骤 步骤1:以user_login用户身份并使用telnet登录Linux服务器,按照提示创建自己的账户和口令。 步骤 2:使用新创建的用户账户和口令登录Linux系统,察看登录后的界面。 步骤3:使用pwd命令察看当前的工作目录,然后用ls 命令查看当前目录下的内容,尝试使用-a,-l,-F,-A,-lF等不同选项并比较不同之处。 步骤4:在当前目录下建立一个名为test的新目录,然后将工作目录切换到test下,尝试将/etc目录下的文件passwd拷贝到该目录下(cp 源文件目的目录)。察看当前目录下的passwd文件的属主和文件权限。

2 步骤5:尝试向当前目录下的passwd文件和/etc/passwd 文件分别写入一些新内容(可使用echo “字符串” >>文件的命令),看看操作能否成功,如果不能成功,请说明原因。用cat命令浏览文件password的内容,用more命令进行浏览翻页操作,再用less命令浏览文件的内容。比较这几个命令的不同之处 步骤6:用ls命令查看test下文件的权限,用mv命令更改文件password的文件名为test.txt,尝试用chown和chgrp更改文件的属主为root、组为root,看看能否成功,不成功,请说明原因。尝试用chomd将文件权限为“-rw-------”。看看能否成功,不成功,请说明原因。 3 步骤7:用rm命令删除test目录下的所有文件,再用rmdir命令删除test目录。(想一想有没有一条命令将目录及目录下的所有文件删除,写出这条命令) 步骤8:使用ps命令查看当前系统内的进程,并利用man命令获取ps命令的参数,写出获取当前终端进程执行情况的ps命令。 4 步骤9:使用df命令查看当前系统已安装的文件系统的空间使用情况,记录结果。

Linux源代码分析_存储管理

文章编号:1004-485X (2003)03-0030-04 收稿日期:2003-05-10 作者简介:王艳春,女(1964 ),副教授,主要从事操作系统、中文信息处理等方面的研究工作。 Linux 源代码分析 存储管理 王艳春 陈 毓 葛明霞 (长春理工大学计算机科学技术学院,吉林长春130022) 摘 要:本文剖析了Linux 操作系统的存储管理机制。给出了Linux 存储管理的特点、虚存的实现方法,以及主要数据结构之间的关系。 关键词:Linux 操作系统;存储管理;虚拟存储中图分类号:T P316 81 文献标识码:A Linux 操作系统是一种能运行于多种平台、源代码公开、免费、功能强大、与Unix 兼容的操作系统。自其诞生以来,发展非常迅速,在我国也受到政府、企业、科研单位、大专院校的重视。我们自2000年开始对Linux 源代码(版本号是Linux 2 2 16)进行分析,首先剖析了进程管理和存储管理部分,本文是有关存储管理的一部分。主要介绍了Linux 虚存管理所用到的数据结构及其相互间的关系,据此可以更好地理解其存储管理机制,也可以在此基础上对其进行改进或在此后的研究中提供借鉴作用。作为一种功能强大的操作系统,Linux 实现了以虚拟内存为主的内存管理机制。即能够克服物理内存的局限,使用户进程在透明方式下,拥有比实际物理内存大得多的内存。本文主要阐述了Linux 虚存管理的基本特点和主要实现技术,并分析了Linux 虚存管理的主要数据结构及其相互关系。 1 Lin ux 虚存管理概述 Linux 的内存管理采用虚拟页式管理,使用多级页表,动态地址变换。进程在运行过程中可以动态浮动和扩展,为用户提供了透明的、灵活有效的内存使用方式。 1)32 bit 虚拟地址 在Linux 中,进程的4GB 虚存需通过32 bit 地址进行寻址。Linux 中虚拟地址与线性地址为同一概念,虚拟地址被分成3个子位段,而大小为4k,如图1所示。 2)Linux 的多级页表结构 图1 32位虚拟地址 标准的Linux 的虚存页表为三级页表,依次为页目录(Pag e Directory PGD)、中间页目录(Pag e Middle Directory PMD )、页表(Page Table PT E )。在i386机器上Linux 的页表结构实际为两级,PGD 和PMD 页表是合二为一的。所有有关PMD 的操作关际上是对PGD 的操作。所以源代码中形如*_pgd _*()和*_pmd_*()函数实现的功能也是一样的。 页目录(PGD)是一个大小为4K 的表,每一个进程只有一个页目录,以4字节为一个表项,分成1024个表项(或称入口点),表项的索引即为32位虚拟地址的页目录,该表项的值为所指页表的起始地址。页表(PTE)的每一个入口点的值为此表项所指的一页框(page frame),页表项的索引即为32位虚拟地址中的页号。页框(page reame)并不是物理页,它指的是虚存的一个地址空间。 3) 页表项的格式 图2 Linux 中页目录项和页表项格式 4)动态地址映射 Linux 虚存采用动态地址映射方式,即进程的地址空间和存储空间的对应关系是在程序的执行过 第26卷第3期长春理工大学学报 Vol 26N o 32003年9月 Journal of Changchun University of Science and T echnology Sep.2003

Linux实验报告

Linux实验 一、实验目的 1. 了解Linux基本使用方法; 2. 掌握Linux基本设置方式; 3. 掌握Linux基本操作命令使用。 二、内容要求 1. 了解进程管理、文件管理与内存管理 2.掌握系统设置文件与命令 3. 熟练使用系统操作与维护命令 4. 熟练使用系统操作与维护命令 三、实验原理 Linux 系统常用命令格式: command [option] [argument1] [argument2] ... 其中option以“-”开始,多个option可用一个“-”连起来,如 “ls-l -a”与“ls-la”的效果是一样的。根据命令的不同,参数 分为可选的或必须的;所有的命令从标准输入接受输入,输出结果显示在 标准输出,而错误信息则显示在标准错误输出设备。可使用重定向功能对这 些设备进行重定向。如: ls –lh > a.txt 命令在正常执行结果后返回一个0值,如果命令出错可未完全完成,则返回 一个非零值(在shell中可用变量$?查看)。在shell script中可用此返 回值作为控制逻辑的一部分。 DSL命令操作: 帮助命令: man 获取相关命令的帮助信息 例如:man dir 可以获取关于dir的使用信息。 info 获取相关命令的详细使用方法 例如:info info 可以获取如何使用info的详细信息。 基本操作: echo 显示字符串 pwd 显示当前工作目录 ls 查看当前文件夹内容 ls -a 查看当前文件夹内容(包括隐藏项) ls -l 查看当前文件夹内容(详细) ls / 查看根目录内容 cd / 移动到根目录

pwd 显示当前工作目录 ls -al 查看根目录文件夹内容(详细情况并包括隐藏项) cd /home/dsl 回到“家”目录 pwd 显示当前工作目录 df -h 显示剩余磁盘空间,参数“-h”表示适合人读取(human readable) du -h 显示文件夹(及子文件夹)所占空间 mkdir fd0 在当前目录下创建目录fd0 touch a.txt 创建一个空文件a.txt ls / -lh > a.txt 利用重定向功能将根目录中的内容写入a.txt。 cat a.txt 显示a.txt内容 wc a.txt 显示a.txt的行数,字数与字节数 find / -name *conf 在根目录下(包括子目录)查找以conf结尾的文件 sudo mount /dev/fd0 fd0 将软盘镜像挂载到目录fd0上 cd fd0 进入软盘镜像所挂载的目录 ls -lh 查看软盘镜像中的文件 cd .. “..”表示进入上一层目录 gzip a.txt 使用gzip压缩a.txt ls -lh 查看当前文件夹 sudo cp a.txt.gz fd0/ 将a.txt复制到fd0目录下,即将其复制到软盘镜像中 sudo mv fd0/a.txt.gz ./ 将a.txt移动到当前目录下,“.”表示当前目录 sudo umount /dev/fd0 将软盘镜像卸载 ls fd0 显示fd0 目录内容 gzip -d a.txt.gz 解压缩a.txt.gz ls -lh 查看当前文件夹 权限管理: 假设当前处于/home/dsl 目录下,且有a.txt(文件)与fd0(目录),当前用户名为dsl。 sudo cat /etc/passwd 用户 sudo cat /etc/shadow 密码 sudo cat /etc/group 组 users 查看当前登录用户 sudo chmod -x fd0 更改文件夹权限 ls fd0 fd0不能被执行,则意味着无法打开! sudo chmod +x fd0 更改文件夹权限 ls fd0 fd0能被打开 sudo chown root fd0 更改目录fd0的所有者 ls -lh 注意看fd0目录的属性 sudo chown dsl:root fd0 更改目录fd0的所有者为dsl,所属组为root ls -lh 注意看fd0目录的属性 chmod a-r a.txt 现在a.txt不具有“读”权限,不能被读取

相关主题
文本预览
相关文档 最新文档