进程就是处于执行期的程序(目标代码存放在某种存储介质上,如内存)。
进程不只局限于可执行代码,还包括其他资源:打开的文件,挂起的信号,内核数据结构,内存地址空间以及至少一个执行线程。
进程是出于执行期的程序和相关资源的总称
执行线程,简称线程,是进程中活动的对象。每个线程都拥有一个独立的程序计数器(即PC),栈和一组寄存器。
内核调度的对象是线程而不是进程
可以说内核是进程——资源分配的最小单位,线程——程序执行的最小单位
进程有独立的地址空间,线程没有单独的地址空间(同一进程内的线程共享进程的地址空间,如果一个进程只有一个线程的话,那么就相当这个线程独自占有内存地址空间了)
现代操作系统中,进程提供两种虚拟机之:虚拟处理器和虚拟内存:虚拟处理器让进程觉得自己独享处理器,虚拟内存让进程觉得自己独享整个内存资源。线程之间可以共享虚拟内存(地址空间),但是每个都拥有自己的虚拟处理器。
内核线程:Linux把所有的线程都当成进程来实现,没有特别的调度算法或者特殊的数据结构来表示线程。线程被视为一个与其他进程共享某些资源的进程,如地址空间。
内核线程和普通进程的区别在于内核线程没有独立的地址空间(实际是指向地址空间的mm指针被设置为NULL),它只在内核空间中运行,从来不切换到用户空间中。创建内核线程是kthreadd内核进程而创建的。
多线程的好处:
1.使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式。我们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间。而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。。
2.对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。
进程间通信:
现在linux使用的进程间通信方式:
(1)管道(pipe)和有名管道(FIFO)
管道是一种?半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系(父子进程)的进程间使用。
有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信
(2)信号(signal)
用于通知接收进程某个事件已经发生。
(3)信号量信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
(4)消息队列
消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
(5)共享内存
共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。
(6)套接字(socket)
套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同主机间的进程通信。
线程间通信:主要是共享数据空间,要注意到是防止数据的并发访问
锁机制:包括互斥锁、条件变量、读写锁
互斥锁提供了以排他方式防止数据结构被并发修改的方法。
使用条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。
读写锁允许多个线程同时读共享数据,而对写操作是互斥的。
* 信号量机制(Semaphore):包括无名线程信号量和命名线程信号量
* 信号机制(Signal):类似进程间的信号处理
防止若不能处理好数据的并发,就会造成各执行线程之间相互覆盖数据,从而产生BUG,是系统不稳定。
执行线程指正在运行执行的代码:如,一个在内核执行的进程,一个中断处理程序或一个线程。
____________________________________________________________
初识内核线程
内核线程(thread)或叫守护进程(daemon),在操作系统中占据相当大的比例,当Linux操作系统启动以后,尤其是X window也启动以后,你可以用”ps -ef”命令查看系统中的进程,这时会发现很多以”d”结尾的进程名,确切说名称显示里面加 "[]"的,这些进程就是内核线程。
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)
内核线程也可以叫内核任务,例如,磁盘高速缓存的刷新,网络连接的维护,页面的换入换出等等。在Linux中,内核线程与普通进程有一些本质的区别,从以下几个方面可以看出二者之间的差异:
? 内核线程能够访问内核中数据,调用内核函数,而普通进程只有通过系统调用才能执行内核中的函数;
? 内核线程只运行在内核态,而普通进程既可以运行在用户态,也可以运行在内核态;
? 因为内核线程指只运行在内核态,因此,它只能使用大于PAGE_OFFSET(3G)的地址空间。另一方面,不管在用户态还是内核态,普通进程可以使用4GB的地址空间。