程序编程代码大全 c代码检查工具( 二 )


copy_process() 函数的C语言源代码
copy_process() 函数的代码也是比较长的,在我手上的Linux系统中,达到了近 400 行,不过代码的整体逻辑是清晰的:
(1)copy_process() 函数首先检查了一些标志位,接着调用 dup_task_struct() 函数为新进程创建内核栈,以及上一节提到的 thread_info 和 task_struct 结构:
调用 dup_task_struct() 函数为新进程创建内核栈
创建后,接下来的 arch_dup_task_struct() 函数会将 orig 结构拷贝给新创建的结构,查看相关C语言代码,这一过程是清晰的:
拷贝给新创建的结构
此时子进程和父进程的描述符是完全相同的 。
(2)接下来,需要检查一些标志位和统计信息,相关的C语言代码如下,请看:
检查一些标志位和统计信息
(3)将一些统计量清零,以及初始化一些区别成员,此时虽然新进程的 task_struct 结构体大多成员未被修改,但是父子进程已经有所区别 。这一过程的相关C语言代码片段如下,请看:
将一些统计量清零,以及初始化一些区别成员
(4)将新创建的子进程状态设置为 TASK_UNINTERRUUPTIBLE,确保其暂时不会被投入运行,这一过程的C语言代码相对简单 。
(5)调用 alloc_pid() 函数为新进程分配一个独一无二的 pid,相关C语言代码如下,请看:
为新进程分配一个独一无二的 pid
(6)根据 clone() 函数的参数标志位,拷贝或共享已经打开的文件、文件系统、信号处理函数、进程地址空间等资源,例如下面这段C语言代码:
拷贝或共享已经打开的资源
(7)将为新进程创建的 task_struct 结构体的指针返回给调用者,也即 do_fork() 函数 。此时新创建的进程还没有被投入运行 。
现在回到 do_fork() 函数 。如果调用 clone() 函数时,没有传递 CLONE_STOPPED 参数,新创建的进程将被唤醒,并投入运行,这一过程的C语言代码如下:
唤醒,并投入运行
到这里,一个新的进程就被 Linux 创建完毕了 。

Linux 内核有意让新创建的子进程先运行,因为子进程常常会立即调用 exec() 函数加载新的程序到内存中运行,这样就避免了写时拷贝的额外开销 。如果父进程首先执行,显然极有可能开始往地址空间写入操作,导致拷贝动作发生 。
小结本节详细的从C语言代码层面分析了Linux内核创建进程的过程,可见,即使是复杂的操作系统代码,也是通过一系列基本C语言语法和函数实现的 。那么,Linux 是如何创建线程的呢?之前我们曾经提到,Linux 系统并不特别区分进程和线程,线程其实是一种特殊的进程,Linux 是如何实现这一“特殊”过程的呢?限于篇幅,下一节再说了,敬请关注 。
点个赞再走吧
【程序编程代码大全 c代码检查工具】欢迎在评论区一起讨论,质疑 。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦 。

推荐阅读