《第4章程序进程和线程精选PPT.ppt》由会员分享,可在线阅读,更多相关《第4章程序进程和线程精选PPT.ppt(28页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第第4章章 程序程序进程和程和线程程第1页,本讲稿共28页4.1 4.1 程序、进程和线程的概念程序、进程和线程的概念在计算机上运行的程序是一组指令及指令参数的组合,在计算机上运行的程序是一组指令及指令参数的组合,指令按照既定的逻辑控制计算机运行。进程则是运行着的程指令按照既定的逻辑控制计算机运行。进程则是运行着的程序,是操作系统执行的基本单位。线程则是为了节省资源而序,是操作系统执行的基本单位。线程则是为了节省资源而可以在同一个进程中共享资源的一个执行单位。可以在同一个进程中共享资源的一个执行单位。第2页,本讲稿共28页4.1.1 4.1.1 程序和进程的差别程序和进程的差别进程概念和程序概
2、念最大的不同之处在于:进程概念和程序概念最大的不同之处在于:进程是动态的,而程序是静态的。进程是动态的,而程序是静态的。进程有一定的生命期,而程序是指令的集合,本身无进程有一定的生命期,而程序是指令的集合,本身无“运动运动”的含义。没有建立进程的程序不能作为的含义。没有建立进程的程序不能作为1个独立单位个独立单位得到操作系统的认可。得到操作系统的认可。一个进程只能对应一个程序,一个程序可以对应多个进一个进程只能对应一个程序,一个程序可以对应多个进程。进程和程序的关系就像戏剧和剧本之间的关系。程。进程和程序的关系就像戏剧和剧本之间的关系。第3页,本讲稿共28页4.1.2 Linux4.1.2 L
3、inux环境下的进程环境下的进程Linux的进程操作方式主要有产生进程、终止进程,并的进程操作方式主要有产生进程、终止进程,并且进程之间存在数据和控制的交互,即进程间通信和同步。且进程之间存在数据和控制的交互,即进程间通信和同步。1进程的产生过程进程的产生过程2进程的终止方式进程的终止方式3进程之间的通信进程之间的通信4进程之间的同步进程之间的同步第4页,本讲稿共28页4.1.3 4.1.3 进程和线程进程和线程线程和进程是另一对有意义的概念,主要区别和联系如线程和进程是另一对有意义的概念,主要区别和联系如下:下:进程是操作系统进行资源分配的基本单位,进程拥有完进程是操作系统进行资源分配的基本
4、单位,进程拥有完整的虚拟空间。进行系统资源分配的时候,除了整的虚拟空间。进行系统资源分配的时候,除了CPU资源之资源之外,不会给线程分配独立的资源,线程所需要的资源需要共外,不会给线程分配独立的资源,线程所需要的资源需要共享。享。线程是进程的一部分,如果没有进行显示的线程分配,线程是进程的一部分,如果没有进行显示的线程分配,可以认为进程是单线程的;如果进程中建立了线程,则可以可以认为进程是单线程的;如果进程中建立了线程,则可以认为系统是多现成的。认为系统是多现成的。多线程和多进程是两种不同的概念,虽然二者都是并行多线程和多进程是两种不同的概念,虽然二者都是并行完成功能。但是,多个线程之间像内存
5、、变量等资源在多个完成功能。但是,多个线程之间像内存、变量等资源在多个线程之间可以通过简单的办法共享,多进程则不同,进程间线程之间可以通过简单的办法共享,多进程则不同,进程间的共享方式有限。的共享方式有限。第5页,本讲稿共28页4.2 4.2 进程产生的方式进程产生的方式进程是计算机中运行的基本单位,要产生一个进程,有进程是计算机中运行的基本单位,要产生一个进程,有多种产生方式,例如使用多种产生方式,例如使用fork()函数、函数、system()函数、函数、exec()函数等,这些函数的不同在于其运行环境的构造之间存在函数等,这些函数的不同在于其运行环境的构造之间存在差别,其本质都是对程序运
6、行的各种条件进行设置,在系统差别,其本质都是对程序运行的各种条件进行设置,在系统之间建立一个可以运行的程序。之间建立一个可以运行的程序。第6页,本讲稿共28页4.2.1 4.2.1 进程号进程号每个进程在初始化的时候,系统都分配了一个每个进程在初始化的时候,系统都分配了一个id号,用号,用于标识此进程。在于标识此进程。在Linux中进程号是唯一的,系统可以用这中进程号是唯一的,系统可以用这个值来表示一个进程,描述进程的个值来表示一个进程,描述进程的id号通常叫做号通常叫做PID,即进,即进程程id(process id)。)。PID的变量类型为的变量类型为pid_t。1函数函数getpid()
7、介绍介绍2函数函数getpid()的例子的例子第7页,本讲稿共28页4.2.24.2.2 进程复制进程复制fork()fork()产生进程的方式比较多,产生进程的方式比较多,fork()是其中的一种方式。是其中的一种方式。fork()函数以父进程为蓝本复制一个进程,其函数以父进程为蓝本复制一个进程,其id号和父进程号和父进程id号号不同。在不同。在Linux环境下,环境下,fork()是以写复制实现的,只有内存是以写复制实现的,只有内存等与父进程不同,其他与父进程共享,只有在父进程或者子等与父进程不同,其他与父进程共享,只有在父进程或者子进程进行了修改后,才重新生成一份。进程进行了修改后,才重
8、新生成一份。1函数函数fork()介绍介绍2函数函数fork()的例子的例子第8页,本讲稿共28页4.2.3 system()4.2.3 system()方式方式system()函数调用函数调用shell的外部命令在当前进程中开始的外部命令在当前进程中开始另一个进程。另一个进程。1函数函数system()介绍介绍2函数函数system()的例子的例子第9页,本讲稿共28页4.2.4 4.2.4 进程执行进程执行exec()exec()函数系列函数系列在使用在使用fork()函数和函数和system()函数的时候,系统中都会函数的时候,系统中都会建立一个新的进程,执行调用者的操作,而原来的进程还
9、会建立一个新的进程,执行调用者的操作,而原来的进程还会存在,直到用户显示的退出;而存在,直到用户显示的退出;而exec()族的函数与之前的族的函数与之前的fork()和和system()函数不同,函数不同,exec()族函数会用新进程代替原有族函数会用新进程代替原有的进程,系统会从新的进程运行,新的进程的的进程,系统会从新的进程运行,新的进程的PID值会与原值会与原来进程的来进程的PID值相同。值相同。1函数函数exec()介绍介绍2函数函数ececve()的例子的例子第10页,本讲稿共28页4.2.5 4.2.5 所有用户态进程的产生进程所有用户态进程的产生进程initinit在在Linux
10、系统中,所有的进程都是有父子或者堂兄关系系统中,所有的进程都是有父子或者堂兄关系的,没有哪个进程与其他进程完全独立。除了初始进程的,没有哪个进程与其他进程完全独立。除了初始进程init,系统中每个进程都有一个父进程,新的进程不是被全新的,系统中每个进程都有一个父进程,新的进程不是被全新的创建,新的进程通常是从一个原有的进程进行复制或者克隆创建,新的进程通常是从一个原有的进程进行复制或者克隆的。的。Linux操作系统下的每一个进程都有一个父进程或者兄操作系统下的每一个进程都有一个父进程或者兄弟进程,并且有自己的子进程。弟进程,并且有自己的子进程。第11页,本讲稿共28页4.3 4.3 进程间通讯
11、和同步进程间通讯和同步在在Linux下的多个进程间的通信机制叫做下的多个进程间的通信机制叫做IPC,它是多,它是多个进程之间进行相互沟通的一种方法。在个进程之间进行相互沟通的一种方法。在Linux下有多种进下有多种进程间通信的方法:半双工管道、程间通信的方法:半双工管道、FIFO(命名管道(命名管道)、消息队、消息队列、信号量、共享内存等。使用这些通信机制可以为列、信号量、共享内存等。使用这些通信机制可以为Linux下的网络服务器开发提供灵活而又坚固的框架。下的网络服务器开发提供灵活而又坚固的框架。第12页,本讲稿共28页4.3.1 4.3.1 半双工管道半双工管道管道是一种把两个进程之间的标
12、准输入和标准输出连接管道是一种把两个进程之间的标准输入和标准输出连接起来的机制。管道是一种历史悠久的进程间通信的办法,自起来的机制。管道是一种历史悠久的进程间通信的办法,自从从UNIX操作系统诞生,管道就存在了。操作系统诞生,管道就存在了。1基本概念基本概念2函数函数pipe()介绍介绍3函数函数pipe()的例子的例子4管道阻塞和管道操作的原子性管道阻塞和管道操作的原子性5管道操作原子性的代码管道操作原子性的代码6管道原子性的例子运行结果管道原子性的例子运行结果第13页,本讲稿共28页4.3.2 4.3.2 命名管道命名管道命名管道的工作方式与普通的管道非常相似,但也有一命名管道的工作方式与
13、普通的管道非常相似,但也有一些明显的区别。些明显的区别。在文件系统中命名管道是以设备特殊文件的形式存在的。在文件系统中命名管道是以设备特殊文件的形式存在的。不同的进程可以通过命名管道共享数据。不同的进程可以通过命名管道共享数据。1创建创建FIFO 2FIFO操作操作第14页,本讲稿共28页4.3.3 4.3.3 消息队列消息队列消息队列是内核地址空间中的内部链表,通过消息队列是内核地址空间中的内部链表,通过Linux内内核在各个进程之间传递内容。消息顺序地发送到消息队列中,核在各个进程之间传递内容。消息顺序地发送到消息队列中,并以几种不同的方式从队列中获取,每个消息队列可以用并以几种不同的方式
14、从队列中获取,每个消息队列可以用IPC标识符唯一的进行标识。内核中的消息队列是通过标识符唯一的进行标识。内核中的消息队列是通过IPC的的标识符来区别的,不同的消息队列之间是相对独立的。每个标识符来区别的,不同的消息队列之间是相对独立的。每个消息队列中的消息,又构成一个独立的链表消息队列中的消息,又构成一个独立的链表1消息缓冲区结构消息缓冲区结构2结构结构msgid_ds3结构结构ipc_perm4内核中的消息队列关系内核中的消息队列关系5键值构建函数键值构建函数ftok()5获得消息函数获得消息函数msgget()6发送消息函数发送消息函数msgsnd()7接收消息函数接收消息函数msgrcv
15、():8消息控制函数消息控制函数msgctl()第15页,本讲稿共28页4.3.3 4.3.3 消息队列消息队列第16页,本讲稿共28页4.3.4 4.3.4 消息队列的一个例子消息队列的一个例子本例在建立建立消息队列后,打印其属性,并在每次发本例在建立建立消息队列后,打印其属性,并在每次发送和接收后均查看其属性,最后对消息队列进行了修改。送和接收后均查看其属性,最后对消息队列进行了修改。1显示消息属性的函数显示消息属性的函数msg_show_attr()2主函数主函数main()第17页,本讲稿共28页4.3.5 4.3.5 信号量信号量信号量是一种计数器,用来控制对多个进程共享的资源信号量
16、是一种计数器,用来控制对多个进程共享的资源所进行的访问。它们常常被用作一个锁机制,在某个进程正所进行的访问。它们常常被用作一个锁机制,在某个进程正在对特定资源进行操作时,信号量可以防止另一个进程去访在对特定资源进行操作时,信号量可以防止另一个进程去访问它。生产者和消费者的模型是信号量的典型使用。问它。生产者和消费者的模型是信号量的典型使用。本小节中介绍了信号量的概念和常用的函数,并对信号本小节中介绍了信号量的概念和常用的函数,并对信号量进行包装形成了一整套用户可以理解的信号量函数。量进行包装形成了一整套用户可以理解的信号量函数。1信号量数据结构信号量数据结构2新建信号量函数新建信号量函数sem
17、get()3信号量操作函数信号量操作函数semo()4控制信号量参数控制信号量参数semctl()5一个信号量操作的例子一个信号量操作的例子第18页,本讲稿共28页4.3.6 4.3.6 共享内存共享内存共享内存是多个进程之间共享内存区域的一种进程间通共享内存是多个进程之间共享内存区域的一种进程间通信方式,它是在多个进程之间进行对内存段进行映射的方式信方式,它是在多个进程之间进行对内存段进行映射的方式实现内存共享的。这是实现内存共享的。这是IPC最快捷的方式,因为共享内存方最快捷的方式,因为共享内存方式的通信没有中间过程,而管道、消息队列等方式的方式则式的通信没有中间过程,而管道、消息队列等方
18、式的方式则是需要将数据通过中间机制进行转换;与此相反,共享内存是需要将数据通过中间机制进行转换;与此相反,共享内存方式直接将某段内存段进行映射,多个进程间的共享内存是方式直接将某段内存段进行映射,多个进程间的共享内存是同一块的物理空间,仅仅是地址不同而已,因此不需要进行同一块的物理空间,仅仅是地址不同而已,因此不需要进行复制,可以直接使用硕慰占洹复制,可以直接使用硕慰占洹1创建共享内存函数创建共享内存函数shmget()2获得共享内存地址函数获得共享内存地址函数shmat()3删除共享内存函数删除共享内存函数shmdt()4共享内存控制共享内存控制shmctl()5一个共享内存的例子一个共享内
19、存的例子第19页,本讲稿共28页4.3.7 4.3.7 信号信号信号(信号(signal)机制是)机制是UNIX系统中最为古老的进程之系统中最为古老的进程之间的通信机制。它用于在一个或多个进程之间传递异步信号。间的通信机制。它用于在一个或多个进程之间传递异步信号。信号可以由各种异步事件产生,例如键盘中断等。信号可以由各种异步事件产生,例如键盘中断等。Shell也也可以使用信号将作业控制命令传递给它的子进程。可以使用信号将作业控制命令传递给它的子进程。Linux系统中定义了一系列的信号,这些信号可以由内系统中定义了一系列的信号,这些信号可以由内核产生,也可以由系统中的其他进程产生,只要这些进程有
20、核产生,也可以由系统中的其他进程产生,只要这些进程有足够的权限。足够的权限。1信号截取函数信号截取函数signal()2向进程发送信号函数向进程发送信号函数kill()和和raise()第20页,本讲稿共28页4.4 Linux4.4 Linux下的线程下的线程线程的概念早在线程的概念早在60年代就被提出,但是在操作系统中年代就被提出,但是在操作系统中真正使用多线程实在真正使用多线程实在80年代的中期,在使用线程方面,年代的中期,在使用线程方面,Solaris是其中的先驱。在传统的是其中的先驱。在传统的UNIX系统中,线程的概念系统中,线程的概念也被使用,但是一个线程对应着一个进程,因此多线程
21、编程也被使用,但是一个线程对应着一个进程,因此多线程编程了多进程,线程的真正有点没有得到发挥。现在,多线程的了多进程,线程的真正有点没有得到发挥。现在,多线程的技术在操作系统中已经得到普及、被很多操作系统所采用,技术在操作系统中已经得到普及、被很多操作系统所采用,其中包括其中包括Windows操作系统和操作系统和Linux系统。与传统的进程相系统。与传统的进程相比较,用线程来实现相同的同能有如下的优点:比较,用线程来实现相同的同能有如下的优点:系统资源消耗低系统资源消耗低速度快速度快线程间的数据共享比进程间容易得多线程间的数据共享比进程间容易得多第21页,本讲稿共28页4.4.1 4.4.1
22、多线程编程实例多线程编程实例Linux系统下的多线程遵循系统下的多线程遵循POSIX标准,叫做标准,叫做pthread,读者可以使用,读者可以使用“man pthread”在在Linux系统下查看系统对系统下查看系统对线程的解释。编写线程的解释。编写Linux下的线程需要包含头文件下的线程需要包含头文件pthread.h,在生成可执行文件的时候需要链接库,在生成可执行文件的时候需要链接库libpthread.a或者或者libpthread.so。第22页,本讲稿共28页4.4.2 Linux4.4.2 Linux下线程创建函数下线程创建函数pthread_createpthread_creat
23、e()()在在4.4.1小节的例子中,用到了两个线程相关的函数小节的例子中,用到了两个线程相关的函数pthread_create()和和pthread_join()。函数。函数pthread_create()用于创建一个线用于创建一个线程,函数程,函数pthread_join()等待一个线程的退出。等待一个线程的退出。在函数在函数pthread_create()函数调用时,传入的参数有线函数调用时,传入的参数有线程属性、线程函数、线程函数变量,用于生成一个某种特性程属性、线程函数、线程函数变量,用于生成一个某种特性的线程,线程中执行线程函束。创建线程使用函数的线程,线程中执行线程函束。创建线程
24、使用函数pthread_create(),它的原型为:,它的原型为:int pthread_create(pthread_t *thread,pthread_attr_t*attr,void*(*start_routine)(void*),void*arg);第23页,本讲稿共28页4.4.3 4.4.3 线程的结束函数线程的结束函数pthread_join()pthread_join()和和pthread_exitpthread_exit()()函数函数pthread_join()用来等待一个线程运行结束。这个用来等待一个线程运行结束。这个函数是阻塞函数,一直到被等待的线程结束为止,函数才返
25、函数是阻塞函数,一直到被等待的线程结束为止,函数才返回并且收回被等待线程的资源。函数原型为:回并且收回被等待线程的资源。函数原型为:extern int pthread_join _P(pthread_t _th,void*_thread_return);第24页,本讲稿共28页4.4.4 4.4.4 线程的属性线程的属性在上例中,用在上例中,用pthread_create()函数创建线程时,使用函数创建线程时,使用了默认参数,即将该函数的第二个参数设为了默认参数,即将该函数的第二个参数设为NULL。通常来。通常来说,建立一个线程的时候,使用默认属性就够了,但是很多说,建立一个线程的时候,使用
26、默认属性就够了,但是很多时候需要调整线程的属性,特别是线程的优先级。时候需要调整线程的属性,特别是线程的优先级。1线程的属性结构线程的属性结构2线程的优先级线程的优先级3线程的绑定状态线程的绑定状态4线程的分离状态线程的分离状态第25页,本讲稿共28页4.4.5 4.4.5 线程间的互斥线程间的互斥互斥锁是用来保护一段临界区的,它可以保证某时间段互斥锁是用来保护一段临界区的,它可以保证某时间段内只有一个线程在执行一段代码或者访问某个资源。下面一内只有一个线程在执行一段代码或者访问某个资源。下面一段代码是一个生产者段代码是一个生产者/消费者的实例程序程序,生产者生产消费者的实例程序程序,生产者生
27、产数据,消费者消耗数据,它们共用一个变量,每次只有一个数据,消费者消耗数据,它们共用一个变量,每次只有一个线程访问此公共变量:线程访问此公共变量:1线程互斥的函数介绍线程互斥的函数介绍2线程互斥函数的例子线程互斥函数的例子第26页,本讲稿共28页4.4.6 4.4.6 线程中使用信号量线程中使用信号量信号量的主要函数有信号量初始化函数信号量的主要函数有信号量初始化函数sem_init()、信、信号量的销毁函数号量的销毁函数sem_destroy()、信号量的增加函数、信号量的增加函数sem_post()、信号量的减少函数、信号量的减少函数sem_wait()等。还有一个函数等。还有一个函数se
28、m_trywait(),它的含义与互斥的函数,它的含义与互斥的函数pthread_mutex_trylock()是一是一致的,先对资源是否可用进行判断。函数的原型在头文件致的,先对资源是否可用进行判断。函数的原型在头文件semaphore.h中定义。中定义。1线程信号量初始化函数线程信号量初始化函数sem_init()2线程信号量增加函数线程信号量增加函数sem_post()3线程信号量等待函数线程信号量等待函数sem_wait()4线程信号量销毁函数线程信号量销毁函数sem_destroy()5线程信号量的例子线程信号量的例子第27页,本讲稿共28页4.5 4.5 小结小结本章介绍了本章介绍
29、了Linux环境下进程和线程的概念和编程方法。环境下进程和线程的概念和编程方法。进程、线程和程序概念的异同主要集中于进程和程序之进程、线程和程序概念的异同主要集中于进程和程序之间的动态和静态、进程和线程之间的运行规模的大小之分。间的动态和静态、进程和线程之间的运行规模的大小之分。进程的产生和消亡从系统的层面来看对应着资源的申请、变进程的产生和消亡从系统的层面来看对应着资源的申请、变量的设置、运行时的调度、及消亡时的资源释放和变量重置。量的设置、运行时的调度、及消亡时的资源释放和变量重置。进程间的通信和同步的方法主要有管道、消息队列、信进程间的通信和同步的方法主要有管道、消息队列、信号量、共享内
30、存以及信号机制。这些机制都是号量、共享内存以及信号机制。这些机制都是UNIX系统系统IPC的典型方法。的典型方法。Linux的线程是一个轻量级的进程,使用线程来编写程的线程是一个轻量级的进程,使用线程来编写程序比进程对系统的负载要低,重要的是共用变量和资源要比序比进程对系统的负载要低,重要的是共用变量和资源要比进程的方法简单的多。进程的方法简单的多。Linux下的线程并不是现代线程的典下的线程并不是现代线程的典型概念,例如没有型概念,例如没有POSIX所规定的挂起、恢复运行等机制,所规定的挂起、恢复运行等机制,它是在它是在Linux进程的基础上的一个发展延伸。进程的基础上的一个发展延伸。第28页,本讲稿共28页