Linux进程
进程与线程
-------------------------------------------------------------------------------------------------------------------------
Linux并不区分进程和线程,线程只是一种特别的进程,Linux并没有使用特别的数据结构或调度算法来标识线程。
每一个进程都有一个内核栈,保存着进程属性等信息。
进程描述符由task_struct来表示,每个进程可从slab allocator动态获取的 thread_info,该结构中有指向 task_struct 的数据成员 task.
进程创建
-------------------------------------------------------------------------------------------------------------------------
进程的创建过程可以分为两部分: fork() 和 exec()
进程终止
-------------------------------------------------------------------------------------------------------------------------
进程终止通过调用exit()来实现。
fork() -- 复制当前进程, 对应的内核函数为sys_fork()
-------------------------------------------------------------------------------------------------------------------------
1) 在fork之后是父进程先执行还是子进程先执行是不确定的,子进程和父进程继续执行fork之后的指令。
2)子进程是父进程的复制品。例如,子进程获得父进程数据空间、堆和栈的复制品。注意,这是子进程所拥有的拷贝。父、子进程并不共享这
些存储空间部分。如果正文段是只读的,则父、子进程共享正文段,现在很多的实现并不做一个父进程数据段和堆的完全拷贝,因为在fork之后经常跟随着
exec, 如此一来,所有的复制将会白费。作为替代,使用了在写时复制的技术。这些区域由父、子进程共享,而且内核将它们的存取许可权改变为只读的。
如果有进程试图修改这些区域,则内核为有关部分,典型的是虚存系统中的“页”,做一个拷贝。
3)所有由父进程打开的描述符都被复制到子进程中,父、子进程每个相同的打开描述符共享一个文件表项
4) 父进程设置的锁、pending signal,子进程不继承
Refer to
http://blog.chinaunix.net/u1/58371/showart.php?id=2202536
exec() -- 创建新的地址空间,加载可执行文件并开始运行
-------------------------------------------------------------------------------------------------------------------------
kernel_thread() -- 创建内核线程
-------------------------------------------------------------------------------------------------------------------------
pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
内核线程与普通进程的不同点在于:
1) 内核线程只运行于内核态,而普通进程可以在用户态和内核态之间随意切换。
2) 内核线程只运行于内核态,所以它只使用大于PAGE_OFFSET的线性地址空间; 而普通进程,无论是在内枋态还是在用户态,则可以使用多达4G的地址空间。
kernel_thread()实现的函数调用链:
kernel_thread -- > do_fork
通过以下调用do_fork:
do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, pregs, 0, NULL, NULL);
阅读(534) | 评论(0) | 转发(0) |