LWP 轻量级线程的意义与实现
转子 http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/
二.Linux 2.4内核中的轻量进程实现
最初的进程定义都包含程序、资源及其执行三部分,其中程序通常指代码,资源在操作系统层面上通常包括内存资源、IO资源、信号处理等部分,而程序的执行通常理解为执行上下文,包括对cpu的占用,后来发展为线程。在线程概念出现以前,为了减小进程切换的开销,操作系统设计者逐渐修正进程的概念,逐渐允许将进程所占有的资源从其主体剥离出来,允许某些进程共享一部分资源,例如文件、信号,数据内存,甚至代码,这就发展出轻量进程的概念。Linux内核在2.0.x版本就已经实现了轻量进程,应用程序可以通过一个统一的clone()系统调用接口,用不同的参数指定创建轻量进程还是普通进程。在内核中,clone()调用经过参数传递和解释后会调用do_fork(),这个核内函数同时也是fork()、vfork()系统调用的最终实现:
<linux-2.4.20/kernel/fork.c>
int do_fork(unsigned long clone_flags, unsigned long stack_start,
struct pt_regs *regs, unsigned long stack_size)
其中的clone_flags取自以下宏的"或"值:
<linux-2.4.20/include/linux/sched.h>
#define CSIGNAL 0x000000ff
/* signal mask to be sent at exit */
#define CLONE_VM 0x00000100
/* set if VM shared between processes */
#define CLONE_FS 0x00000200
/* set if fs info shared between processes */
#define CLONE_FILES 0x00000400
/* set if open files shared between processes */
#define CLONE_SIGHAND 0x00000800
/* set if signal handlers and blocked signals shared */
#define CLONE_PID 0x00001000
/* set if pid shared */
#define CLONE_PTRACE 0x00002000
/* set if we want to let tracing continue on the child too */
#define CLONE_VFORK 0x00004000
/* set if the parent wants the child to wake it up on mm_release */
#define CLONE_PARENT 0x00008000
/* set if we want to have the same parent as the cloner */
#define CLONE_THREAD 0x00010000
/* Same thread group? */
#define CLONE_NEWNS 0x00020000 /* New namespace group? */
#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD)
在do_fork()中,不同的clone_flags将导致不同的行为,对于LinuxThreads,它使用(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND)参数来调用clone()创建"线程",表示共享内存、共享文件系统访问计数、共享文件描述符表,以及共享信号处理方式。本节就针对这几个参数,看看Linux内核是如何实现这些资源的共享的。
1.CLONE_VM
do_fork()需要调用copy_mm()来设置task_struct中的mm和active_mm项,这两个mm_struct数据与进程所关联的内存空间相对应。如果do_fork()时指定了CLONE_VM开关,copy_mm()将把新的task_struct中的mm和active_mm设置成与current的相同,同时提高该mm_struct的使用者数目(mm_struct::mm_users)。也就是说,轻量级进程没有独立的文件系统相关的信息,进程中任何一个线程改变当前目录、根目录等信息都将直接影响到其他线程。
3.CLONE_FILES
一个进程可能打开了一些文件,在进程结构task_struct中利用files(struct files_struct *)来保存进程打开的文件结构(struct file)信息,do_fork()中调用了copy_files()来处理这个进程属性;轻量级进程与父进程是共享该结构的,copy_files()时仅增加files->count计数。这一共享使得任何线程都能访问进程所维护的打开文件,对它们的操作会直接反映到进程中的其他线程。
4.CLONE_SIGHAND
每一个Linux进程都可以自行定义对信号的处理方式,在task_struct中的sig(struct signal_struct)中使用一个struct k_sigaction结构的数组来保存这个配置信息,do_fork()中的copy_sighand()负责复制该信息;轻量级进程不进行复制,而仅仅增加signal_struct::count计数,与父进程共享该结构。也就是说,子进程与父进程的信号处理方式完全相同,而且可以相互更改。
do_fork()中所做的工作很多,在此不详细描述。对于SMP系统,所有的进程fork出来后,都被分配到与父进程相同的cpu上,一直到该进程被调度时才会进行cpu选择。
尽管Linux支持轻量级进程,但并不能说它就支持核心级线程,因为Linux的"线程"和"进程"实际上处于一个调度层次,共享一个进程标识符空间,这种限制使得不可能在Linux上实现完全意义上的POSIX线程机制,因此众多的Linux线程库实现尝试都只能尽可能实现POSIX的绝大部分语义,并在功能上尽可能逼近。
LWP 轻量级线程的意义与实现的更多相关文章
- .NET 中的轻量级线程安全
对线程安全有要求的代码中,通常会使用锁(lock).自 .NET 诞生以来就有锁,然而从 .NET Framework 4.0 开始,又诞生了 6 个轻量级的线程安全方案:SpinLock, Spin ...
- go实例之轻量级线程goroutine、通道channel与select
1.goroutine线程 goroutine是一个轻量级的执行线程.假设有一个函数调用f(s),要在goroutine中调用此函数,请使用go f(s). 这个新的goroutine将与调用同时执行 ...
- Linux线程 之 线程 线程组 进程 轻量级进程(LWP)
Thread Local Storage,线程本地存储,大神Ulrich Drepper有篇PDF文档是讲TLS的,我曾经努力过三次尝试搞清楚TLS的原理,均没有彻底搞清楚.这一次是第三次,我沉浸gl ...
- 进程、线程、轻量级进程、协程与 go 的 goroutine【转载+整理】
本文内容 进程 线程 协程 Go 中的 goroutine 参考资料 最近,看一些文章,提到"协程"的概念,心想,进程,线程,协程,前两个很容易,任何一本关于操作系统的书都有说,开 ...
- 进程、线程、轻量级进程、协程和go中的Goroutine
进程.线程.轻量级进程.协程和go中的Goroutine 那些事儿电话面试被问到go的协程,曾经的军伟也问到过我协程.虽然用python时候在Eurasia和eventlet里了解过协程,但自己对协程 ...
- Linux下的进程类别(内核线程、轻量级进程和用户进程)--Linux进程的管理与调度(四)
本文中出现的,内核线程,轻量级进程,用户进程,用户线程等概念,如果不太熟悉, 可以参见 内核线程.轻量级进程.用户线程三种线程概念解惑(线程≠轻量级进程) Linux进程类别 虽然我们在区分Linux ...
- Go语言 进程、线程、轻量级进程、协程和go中的Goroutine 那些事儿
原文:http://www.cnblogs.com/shenguanpu/archive/2013/05/05/3060616.html 电话面试被问到go的协程,曾经的军伟也问到过我协程.虽然用py ...
- 进程、线程、轻量级进程、协程与 go 的 goroutine
本文内容 进程 线程 协程 Go 中的 goroutine 参考资料 最近,看一些文章,提到“协程”的概念,心想,进程,线程,协程,前两个很容易,任何一本关于操作系统的书都有说,开发时也经常用,但是协 ...
- Java的线程模型
并发不一定要依赖多线程(如PHP中很常见的多进程并发),但是在Java里面谈论并发,大多数都与线程脱不开关系. 线程是比进程更轻量级的调度执行单位,线程的引入,可以把一个进程的资源分配和执行调度分开, ...
随机推荐
- 求时间差的sql语句。 比如如下数据
msisdn createtime closetime138 2011-5-17 15:30:00:000 2011-5-17 15:30:00:530138 2011-5-17 15:40:00:0 ...
- Caffe学习系列(21):caffe图形化操作工具digits的安装与运行
经过前面一系列的学习,我们基本上学会了如何在linux下运行caffe程序,也学会了如何用python接口进行数据及参数的可视化. 如果还没有学会的,请自行细细阅读: caffe学习系列:http:/ ...
- [MetaHook] Load TGA texture to OpenGL
This function load a *.tga texture file and convert to OpenGL pixel format, uncompress only. #pragma ...
- 树莓派之web服务器搭建
树莓派之web服务器搭建 (一)使用ufw创建防火墙 设置目的:可以完全阻止对树莓派的访问也可以用来配置通过防火墙对特点程序的访问.使用防火墙更好的保护树莓派. 准备工作 1.带有5V电源的树莓派 2 ...
- 20145311利用gdb调试汇编代码
利用GDB调试汇编代码 首先编写c语言原代码,我使用的是同学分析过的代码 #include<stdio.h>short addend1 = 1;static int addend2 = 2 ...
- Opencv step by step - 自适应阈值
上个博客提到的阈值化只是针对图像全局进行阈值化,opencv提供了一个更好的函数cvAdaptiveThreshold,可以做到局部特征的阈值化,这样一来, 整个图像的信息可以被更好的提取. #inc ...
- 零散知识记录-Jira的安装
Jira不支持openjdk,在linux下需要卸载后,装个jdk才行.
- Javascript基础系列之(三)数据类型 (字符串 String)
javascript一共有9种数据类型 字符串 String 数值型 Number 布尔型 Boolean 未定义 Undefine 空值 Null 对象 Object 引用Refernce 列表型 ...
- Memcached——非关系型数据库分布式处理
Memcached登录校验应用: MMCacheWriter.cs类 using Memcached.ClientLibrary; using System; using System.Collect ...
- Day10
会议讨论 628:今天是冲刺的最后一天了,好紧张好激动,我们组还有好些个功能没实现呢,感觉崩崩哒!还要实现选择不同的专业导入不同的课表呢. 601:在修改教师帐号信息的页面要有当密码格式.用户名格式等 ...