`
bigfirebird
  • 浏览: 128781 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

linux 2.6进程与线程

阅读更多
1 >    线程和进程的差别
线程机制支持并发程序设计技术,在多处理器上能真正保证并行处理。而在linux实现线程很特别,linux把所有的线程都当作线程实现。
linux下线程看起来就像普通进程(只是该进程和其他进程共享资源,如地址空间)。上述机制与Microsoft windows或是Sun Solaris实现
差异很大。这些系统提供专门支持线程机制(轻量级进程)。

在现代操作系统中,进程支持多线程。进程是资源管理及分配的最小单元;而线程是程序执行的最小单元。一个进程的组成实体可以分为两大部分:线程集和资源集。进程中的线程是动态的对象,代表了进程指令的执行过程。资源,包括地址空间、打开的文件、用户信息等等,由进程内的线程共享。线程有自己的私有数据:程序计数器,栈空间以及寄存器。

现实中有很多需要并发处理的任务,如数据库的服务器端、网络服务器、大容量计算等。

如果采用多进程的方法,则有如下问题:
      1> fork一个子进程的消耗是很大的,fork是一个昂贵的系统调用。
      2> 各个进程拥有自己独立的地址空间,进程间的协作需要复杂的IPC技术,如消息传递和共享内存等。

线程推广了进程的概念,使一个进程可以包含多个活动(或者说执行序列等等)。多线程的优点和缺点实际上是对立统一的。使用线程的优点在于:

      1> 改进程序的实时响应能力;
      2> 更有效的使用多处理器,真正的并行(parallelism);
      3> 改进程序结构,具备多个控制流;
      4> 通讯方便,由于共享进程的代码和全局数据;
      5> 减少对系统资源的使用。对属于同一个进程的线程之间进行调度切换时不需要调用系统调用,因此将减少额外的消耗,往往一个进程可以启动上千个线程也没有什么问题。

缺点在于:
由于各线程共享进程的地址空间,因此可能会导致竞争,因此对某一块有多个线程要访问的数据需要一些同步技术。


2 >     线程的分类
2.1     内核线程
Linux内核可以看作一个服务进程(管理软硬件资源,响应用户进程的种种合理以及不合理的请求)。内核需要多个执行流并行,为了防止可能的阻塞,多线程化是必要的。内核线程就是内核的分身,一个分身可以处理一件特定事情。Linux内核使用内核线程来将内核分成几个功能模块,像kswapd、kflushd等,这在处理异步事件如异步IO时特别有用。内核线程的使用是廉价的,唯一使用的资源就是内核栈和上下文切换时保存寄存器的空间。支持多线程的内核叫做多线程内核(Multi-Threads kernel )。内核线程的调度由内核负责,一个内核线程处于阻塞状态时不影响其他的内核线程,因为其是调度的基本单位。这与用户线程是不一样的。

2.2用户线程
用户线程在用户空间中实现,内核并没有直接对用户线程进程调度,内核的调度对象和传统进程一样,还是进程本身,内核并不知道用户线程的存在。

由于Linux内核没有轻量级进程(线程)的概念,因此不能独立的对用户线程进行调度,而是由一个线程运行库来组织线程的调度,其主要工作在于在各个线程的栈之间调度。如果一个进程中的某一个线程调用了一个阻塞的系统调用,整个进程就会被调度程序切换为等待状态,其他线程得不到运行的机会。因此linux使用了异步I/O机制。


3 >     内核线程
内核线程(thread)或叫守护进程(daemon),在操作系统中占据相当大的比例,当Linux操作系统启动以后,尤其是X window也启动以后,你可以用”ps -ef”命令查看系统中的进程,这时会发现很多以”d”结尾的进程名,确切说名称显示里面加 "[]"的,这些进程就是内核线程。系统的启动是从硬件->内核->用户态进程的,pid的分配是一个往前的循环的过程,所以随系统启动的内核线程的pid往往很小。

UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 09:42 ?        00:00:01 /sbin/init
root         2     0  0 09:42 ?        00:00:00 [kthreadd]
root         3     2  0 09:42 ?        00:00:00 [migration/0]
root         4     2  0 09:42 ?        00:00:00 [ksoftirqd/0]
root         5     2  0 09:42 ?        00:00:00 [watchdog/0]
root         6     2  0 09:42 ?        00:00:00 [events/0]
root         7     2  0 09:42 ?        00:00:00 [khelper]
root        40     2  0 09:42 ?        00:00:00 [kblockd/0]
root        64     2  0 09:42 ?        00:00:00 [kseriod]
root       110     2  0 09:42 ?        00:00:00 [pdflush]
root       111     2  0 09:42 ?        00:00:00 [pdflush]
root       112     2  0 09:42 ?        00:00:00 [kswapd0]
root       151     2  0 09:42 ?        00:00:00 [aio/0]
root      1327     2  0 09:42 ?        00:00:00 [ksuspend_usbd]
root      1330     2  0 09:42 ?        00:00:00 [khubd]
root      1362     2  0 09:42 ?        00:00:00 [ata/0]
root      1370     2  0 09:42 ?        00:00:00 [ata_aux]
root      1428     2  0 09:42 ?        00:00:00 [scsi_eh_0]
root      1430     2  0 09:42 ?        00:00:01 [scsi_eh_1]
root      2304     2  0 09:42 ?        00:00:00 [kjournald]
root      2507     1  0 09:42 ?        00:00:00 /sbin/udevd --daemon
root      2787     2  0 09:42 ?        00:00:00 [kgameportd]
root      3698     2  0 09:42 ?        00:00:00 [kapmd]
root      3872     2  0 09:42 ?        00:00:00 [kjournald]



3.1     内核线程
      events 处理内核事件 很多软硬件事件(比如断电,文件变更)被转换为events,并分发给对相应事件感兴趣的线程进行响应

      ksoftirqd 处理软中断 硬件中断处理往往需要关中断,而这个时间不能太长,否则会丢失新的中断。所以中断处理的很大一部分工作移出,转给任劳任怨的ksoftirqd在中断之外进行处理。比如一个网络包,从网卡里面取出这个过程可能需要关中断,但是TCP/IP协议处理就不必关中断了

      kblockd 管理磁盘块读写

      kjournald Ext3文件系统的日志管理 通常每个 _已mount_ 的 Ext3分区会有一个 kjournald看管,各分区的日志是独立

      pdflush dirty内存页面的回写 太多dirty的页面意味着风险,比如故障时候的内容丢失,以及对突发的大量物理内存请求的响应(大量回写会导致糟糕的响应时间)

      kswapd 内存回收 确保系统空闲物理内存的数量在一个合适的范围

      aio 代替用户进程管理io 用以支持用户态的AIO
     


3.2     用户进程

      crond 执行定时任务

      init 为内核创建的第一个线程。引导用户空间服务,管理孤儿线程,以及运行级别的转换
     
      mingetty 等待用户从tty登录

      bash shell进程,一个命令行形式的系统接口;接受用户的命令,并进行解释、执

      sshd ssh登录、文件传输、命令执行 等操作的服务进程

      klogd 从内核信息缓冲区获取打印信息。内核在发现异常的时候,往往会输出一些消息给用户,这个对于故障处理很有用

      syslogd 系统日志进程

      udevd 支持用户态设备操作 (userspace device)
     
     
4>     创建线程 clone_flags   
最初的进程定义都包含程序、资源及其执行三部分,其中程序通常指代码,资源在操作系统层面上通常包括内存资源、IO资源、信号处理等部分,而程序的执行通常理解为执行上下文,包括对cpu的占用,后来发展为线程。在线程概念出现以前,为了减小进程切换的开销,操作系统设计者逐渐修正进程的概念,逐渐允许将进程所占有的资源从其主体剥离出来,允许某些进程共享一部分资源,例如文件、信号,数据内存,甚至代码。应用程序可以通过一个统一的clone()系统调用接口,用不同的参数指定创建轻量进程还是普通进程。在内核中,clone()调用经过参数传递和解释后会调用do_fork(),这个核内函数同时也是fork():



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)


其中的clone_flags取自以下宏的"或"值:

在 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)。也就是说,轻量级进程与父进程共享内存地址空间,由下图示意可以看出mm_struct在进程中的地位:

2.CLONE_FS
task_struct 中利用fs(struct fs_struct *)记录了进程所在文件系统的根目录和当前目录信息,do_fork()时调用copy_fs()复制了这个结构;而对于轻量级进程则仅增加 fs->count计数,与父进程共享相同的fs_struct。也就是说,轻量级进程没有独立的文件系统相关的信息,进程中任何一个线程改变当前目录、根目录等信息都将直接影响到其他线程。

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计数,与父进程共享该结构。也就是说,子进程与父进程的信号处理方式完全相同,而且可以相互更改。


尽管Linux支持轻量级进程,但并不能说它就支持核心级线程,因为Linux的"线程"和"进程"实际上处于一个调度层次,共享一个进程标识符空间,这种限制使得不可能在Linux上实现完全意义上的POSIX线程机制,因此众多的Linux线程库实现尝试都只能尽可能实现POSIX的绝大部分语义,并在功能上尽可能逼近。
分享到:
评论

相关推荐

    Linux 2.6进程调度算法实时性能改进.pdf

    《Linux 2.6进程调度算法实时性能改进》这篇论文主要探讨了Linux 2.6内核中的进程调度算法,并提出了改进策略以增强系统的实时性和吞吐量。Linux操作系统因其开源、多用户、多进程、多线程以及跨平台的优势,在...

    Linux2.6内核标准教程(共计8-- 第1个)

    4.1 进程与线程的概念 129 4.1.1 程序与进程 129 4.1.2 进程与线程 129 4.2 进程描述符 131 4.2.1 进程标识符 132 4.2.2 进程的状态 132 4.2.3 进程上下文 134 4.2.4 当前进程 139 4.3 进程的组织...

    Linux2.6内核实现的是NPTL线程模型

    在Linux2.6内核中,依然采用进程来模拟线程的行为,但新引入了线程组(进程组)的概念。线程组是由一个或多个线程组成的集合,它们共享相同的线程组ID(TID)。在2.4内核之前,每个线程都被视为一个独立的进程,并...

    Linux 2.6内核标准教程(部分)

    第4章详细讲解了进程和线程的概念,以及它们在Linux内核中的实现。特别地,本章深入探讨了Linux内核中著名的O(1)调度器,它是Linux 2.6内核中的一大亮点,极大提升了系统的调度效率。此外,0号进程作为内核的主进程...

    Linux2.6内核标准教程(共计8--第8个)

    4.1 进程与线程的概念 129 4.1.1 程序与进程 129 4.1.2 进程与线程 129 4.2 进程描述符 131 4.2.1 进程标识符 132 4.2.2 进程的状态 132 4.2.3 进程上下文 134 4.2.4 当前进程 139 4.3 进程的组织...

    Linux2.6内核标准教程(共计8--第6个)

    4.1 进程与线程的概念 129 4.1.1 程序与进程 129 4.1.2 进程与线程 129 4.2 进程描述符 131 4.2.1 进程标识符 132 4.2.2 进程的状态 132 4.2.3 进程上下文 134 4.2.4 当前进程 139 4.3 进程的组织...

    \嵌入式linux开发教程之进程与线程--千锋培训

    嵌入式Linux开发教程深入探讨了进程与线程的概念及其在操作系统中的实现,这对于理解和开发高效、并发的嵌入式应用程序至关重要。以下是这些知识点的详细解释: **一、基础知识:线程和进程** 1. **进程**:是操作...

    Linux2.6内核标准教程(共计8--第3个)

    4.1 进程与线程的概念 129 4.1.1 程序与进程 129 4.1.2 进程与线程 129 4.2 进程描述符 131 4.2.1 进程标识符 132 4.2.2 进程的状态 132 4.2.3 进程上下文 134 4.2.4 当前进程 139 4.3 进程的组织...

    Linux2.6内核标准教程(共计8--第7个)

    4.1 进程与线程的概念 129 4.1.1 程序与进程 129 4.1.2 进程与线程 129 4.2 进程描述符 131 4.2.1 进程标识符 132 4.2.2 进程的状态 132 4.2.3 进程上下文 134 4.2.4 当前进程 139 4.3 进程的组织...

    linux-2.6.21.5源代码

    在多处理器系统中,Linux 2.6.21.5内核提供了线程、信号量、互斥锁、条件变量等机制,用于处理并发执行的进程和线程间的同步问题,保证了系统的一致性和正确性。 九、安全与权限 内核的安全模型主要基于用户ID(UID...

    Linux 内核2.6 + ssh

    在Linux 2.6内核中,可能会有多种调度算法,如O(1)调度器,它能快速选择下一个进程,使得系统响应更加迅速。 7. **资源争用**:当多个进程试图访问同一资源时,可能导致资源争用。为解决这个问题,操作系统使用同步...

    嵌入式系统中Linux2.6内核的应用.pdf

    3. **同步原型与共享内存**:Linux2.6支持Fast User-Space Mutexes(FUTEX),允许从用户空间检测线程是否需要阻塞,减少了不必要的系统调用,提升了性能。此外,NUMA(非一致性内存访问)技术为多处理器系统提供了...

    Linux2.6内核标准教程(共计8--第2个)

    4.1 进程与线程的概念 129 4.1.1 程序与进程 129 4.1.2 进程与线程 129 4.2 进程描述符 131 4.2.1 进程标识符 132 4.2.2 进程的状态 132 4.2.3 进程上下文 134 4.2.4 当前进程 139 4.3 进程的组织...

    【干货】linux-2.6.11.12内核源代码及源码注释.zip

    在Linux-2.6.11.12版本的内核中,包含了多个关键领域的源代码和注释,这对于理解操作系统的工作原理以及进行内核级别的编程至关重要。 1. **同步机制**:在多线程环境中,同步是非常关键的,以确保数据的一致性和...

    理解Linux内核2.6.8.1cpu调度

    - **Linux 进程/线程**:Linux 系统通过内核支持进程和线程管理。每个进程都有唯一的进程标识符(PID),而线程则共享相同的地址空间但拥有各自的栈。 #### Linux 调度目标 - **目标市场与调度器的影响**:Linux ...

    Understanding the Linux 2.6.8.1 CPU Scheduler(中文翻译)

    Linux 2.6.8.1 调度器的结构与组件..................................................................135.1 CFS (Completely Fair Scheduler):完全公平调度器..............................135.1.1 Red-Black ...

    嵌入式Linux2.6核硬实时性能研究与优化.pdf

    【嵌入式Linux2.6内核硬实时性能研究与优化】 嵌入式Linux系统在近年来的广泛应用中,尤其在工业控制、航空航天、通信设备等领域,对于硬实时性的需求日益增强。硬实时系统要求系统对特定事件的响应时间具有严格的...

    基于公平策略的Linux2.6调度算法与应用分析.pdf

    Linux 2.6 内核引入了内核态抢占,这意味着即使内核线程也可以被打断,让其他更高优先级的进程获得 CPU。这一特性增强了系统的响应性,特别是对于需要快速响应的交互式应用。 5. **适用的应用环境** O(1) 更适合...

    嵌入式Linux2.6的实时性能研究与优化.pdf

    针对这一问题,本文重点探讨了嵌入式Linux 2.6内核的实时性能研究与优化策略,旨在提高Linux系统的实时性能,以适应更高要求的应用需求。 Linux 2.6内核在多方面表现优异,但在实时性能方面却有明显的不足。具体来...

Global site tag (gtag.js) - Google Analytics