用户进程,用户线程,内核线程
来源:互联网 发布:爆破手机号软件 编辑:程序博客网 时间:2024/05/20 00:35
详细:http://blog.163.com/zhe_wang_2009/blog/static/17228212120123971418489/
总的示意图如下:
Location:arch/x86/kernel/process.c(linux 2.6.38)
Location:arch/x86/kernel/process.c(linux 2.6.38)238 int sys_fork(struct pt_regs *regs) 239 {240 return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);241 }
Location:arch/x86/kernel/process.c(linux 2.6.38)253 int sys_vfork(struct pt_regs *regs) 254 {255 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0,256 NULL, NULL);257 }
259 long260 sys_clone(unsigned long clone_flags, unsigned long newsp,261 void __user *parent_tid, void __user *child_tid, struct pt_regs * regs)262 {263 if (!newsp)264 newsp = regs->sp;265 return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);266 }
Location:kernel/fork.c
1399 long do_fork(unsigned long clone_flags, 1400 unsigned long stack_start,1401 struct pt_regs *regs,1402 unsigned long stack_size,1403 int __user *parent_tidptr,1404 int __user *child_tidptr)1405 {1406 struct task_struct *p;1407 int trace = 0;1408 long nr;
进程,线程,内核线程在内核中都是通过do_fork()完成创建的,那do_fork()是如何体现其功能的多样性的呢?
主要发挥作用的是do_fork()的第一个参数,clone_flags
下面介绍几个常见的clone_flags的取值:
CLONE_VM :子进程共享父进程内存描述符和所有的页表
CLONE_FS :子进程共享父进程所在文件系统的根目录和当前工作目录
CLONE_FILES :子进程共享父进程打开的文件
CLONE_SIGHAND :子进程共享父进程的信号处理程序、阻塞信号和挂起的信号,
使用该标志必须同时设置 CLONE_VM 标志
回给父进程的 SIGCHLD 信号外并无其他特性标志,因此由 fork()
创建的进程不会共享父进程的任何资源。通常子进程会完全复制父
进程的资源,也就是说父子进程相对独立
do_fork()中的参数:
clone_flags :进程各种特性的标志。低字节指定子进程结
束时发送给父进程的信号代码,一般为 SIGCHLD 信号,剩
余三个字节是若干个标志或运算的结果
regs :指向通用寄存器值的指针,当进程从用户态切换到
内核态时通用寄存器中的值会被保存到内核态堆栈中
vfork() : do_fork() 中的 clone_flags 使用了 CLONE_VFORK 和 CLONE_VM 两个标志
CLONE_VFORK 标志使得子进程先于父进程执行,父进程会阻塞到子进程结束或执行新的程序
CLONE_VM 标志使得子进程共享父进程的内存地址空间(父进程的页表项除外)
clone() :与前两个函数不同, clone 通常用于创建轻量级进程.
使用 clone 函数时候通常是自定义的传入 flags 标志,一般
flags 的取值为 CLONE_VM|CLONE_FS|CLONE_FILES|
CLONE_SIGHAND
由上述标志可以看到,轻量级进程通常共享父进程的内存地址
空间、父进程所在文件系统的根目录以及工作目录信息、父进
程当前打开的文件以及父进程所拥有的信号处理函数
通过 pthread_create() 创建的线程最终在内核中是
通过 clone() 完成创建的,而 clone() 最终调用
do_fork 函数
关于kernel_thread()函数(location::arch/x86/kernel/process.c(linux 2.6.38))
从上面的组合的 flag 可以看出,新的内核线程至少会共享父内核278 int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)279 {280 struct pt_regs regs;281 282 memset(®s, 0, sizeof(regs));283 284 regs.si = (unsigned long) fn;285 regs.di = (unsigned long) arg;286 287 #ifdef CONFIG_X86_32288 regs.ds = __USER_DS;289 regs.es = __USER_DS;290 regs.fs = __KERNEL_PERCPU;291 regs.gs = __KERNEL_STACK_CANARY;292 #else293 regs.ss = __KERNEL_DS;294 #endif295 296 regs.orig_ax = -1;297 regs.ip = (unsigned long) kernel_thread_helper;298 regs.cs = __KERNEL_CS | get_kernel_rpl();299 regs.flags = X86_EFLAGS_IF | 0x2;300 301 /* Ok, create the new process.. */302 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);303 }304 EXPORT_SYMBOL(kernel_thread);
线程的内存地址空间。
- Linux内核线程、用户进程,用户线程
- 用户进程,用户线程,内核线程
- linux内核线程 [内核线程 用户进程 用户线程]
- 内核线程、轻量级进程、用户线程
- 内核线程、轻量级进程、用户线程
- 内核线程、轻量级进程、用户线程
- 内核线程、轻量级进程、用户线程
- 内核线程、轻量级进程、用户线程
- 内核线程、轻量级进程、用户线程
- 内核线程、轻量级进程、用户线程
- 内核线程、轻量级进程、用户线程
- 内核线程、轻量级进程、用户线程
- 内核线程、轻量级进程、用户线程、用户进程
- linux内核线程、轻量级进程、用户进程
- 进程,轻量级进程,内核线程,用户线程的区别关系
- Linux内核进程 线程 用户空间线程进程
- 进程,轻量级进程,内核线程,用户线程的区别关系
- 进程,轻量级进程,内核线程,用户线程的区别关系
- oracle exp imp 导入 正在跳过表 plsql 导入表 成功终止 数据 被导入
- 【discuzx2】home_space.htm模板文件解析
- POJ1298 解密,字符移五位输出
- 大话设计模式--访问者模式 Visitor -- C++实现实例
- Documentation/dvb/readme.txt
- 用户进程,用户线程,内核线程
- Tomcat通过数据源访问数据库
- Android的编译过程(一)
- poj 1733 - Parity game(离散化+并查集)
- php中iconv函数使用方法
- redis网络资料汇总
- MINI2440+UDA1341TS分析之二
- 一个完整的maven配置selenium webdriver工程实例(一)
- 一种简单的Visual C++中内存泄漏的检测方法