学习笔记——进程[1]

来源:互联网 发布:12口网络配线架 编辑:程序博客网 时间:2024/05/17 04:20

首先,我们知道,进程是一个东西,是确确实实存在的某个东西,那么,我们写程序怎么表示这些个“东西”的啊,一般就是用结构体了哦,所以,系统中也就有一个结构体表示了“进程”,即: struct task_struct { …… } 利用这个结构体,就可以描述系统中的各个进程了,当然,为了时髦一点,人们一般把这个结构体称之为“进程控制块”,或者用英语说是:PCB。而这个PCB中有哪些东西,我们暂且不管。NND,差距明显啊,人家已经想到了这点,而且设计出了里面应该包括哪些东西——这个结构体中应该包括哪些东西,还是非常头疼的——我们现在还只是考虑到这点,还没法更多地考虑里面应该包括哪些东西! 



      现在我们知道可以有个东西描述进程了,那么,不免要问,这个进程是从哪儿来的?蛋是鸡生的,鸡是蛋里孵化出来的,进程呢?——进程是由进程孵化出来的!好了,再问,那会不会像鸡和蛋一样没有开始啊?当然不对了,系统中存在的首个进程的,第一个进程,我们一般俗称之为“0”号进程,或者也可以说是init进程,很简单,就是初始化进程吗。也就是说,系统中肯定能够冒出一个“0”号进程,然后所有其他的进程都是由这个“0”号进程孵化出来的——和鸡、蛋不一样的。那么这个“0”号进程怎么来的呢?其实很简单,考虑一下,必定是在系统初始化的某个时候产生的,即:
   系统在初始化-〉   系统创建“0”号进程-〉   “0”号进程衍生出所有其他进程


现在知道了,系统中的某个进程必定是由另外一个进程孵化出来的,而某个进程又可以孵化出其他的进程,从而子子孙孙,无穷尽也——错,系统关机,所有进程全部死了——从而构成下面一幅壮观的景象:


 那么,一个进程是如何孵化出另外一个进程的呢?不说大家也应该知道了,肯定是调用了某个函数的结果。想想,系统中此时应该是这个样子的:
某个进程在运行-〉某个进程觉得需要创建一个子进程-〉调用函数开始创建

我们知道,孩子都具有爸妈的遗传基因,而某个进程创建出来的子进程要不要具有父进程的特征呢?简单点说:假如此时父进程打开了某个文件,在进行读取操作,那么子进程要不要也拥有读取该文件的能力呢?想想,好像需要,也好像不需要,看情况而定。


在Linux中,子进程则是遗传了父进程的基因。而系统提供的创建函数有两个:fork()和clone()。这两个函数的区别在于:fork是把父进程所具有的全部资源全部“复制”给了子进程,而clone则是部分复制,某些其他部分则是传递了指针,这个就好像是c++中的传值和传引用的区别。

 下面接下来看看这个父进程是如何衍生出子进程的(采用哪个版本的源代码和怎么介绍这些代码,破费了我很大的脑筋J):

//在我们写程序的时候注意,long是可移植的,而int则随着编译器的不同而不同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 pid = alloc_pidmap();       ……       //开始完成具体的创建子进程工作       p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid);       //这儿,我们在写程序的时候也要注意,如果某个判断的可能性大,      //那么最好放前面,省得多执行语句       if (!IS_ERR(p)) {              ……              ……       } else {              free_pidmap(pid);              pid = PTR_ERR(p);       }       return pid;}


这段代码中比较重要的有两个部分,首先是给子进程分配进程号,然后是利用具体的进程号创建子进程。具体怎么创建法的,由于在系统中,进程涉及到内存管理,文件系统等等,所以以后介绍。

原创粉丝点击