linux多任务
一.进程1.什么是进程进程正在执行的程序实例需要消耗内存和CPU是系统进行资源调度和资源分配的独立单位。系统资源分配的最小单位是进程而 CPU 调度执行的最小单位是线程。进程是由多道程序的并发执行而引出的它和程序是两个截然不同的概念。程序是静态的进程是动态的进程的基本特征是对比单个程序的顺序执行提出的。1)动态性。进程是程序的一次执行它有着创建、活动、暂停、终止等过程具有一定的生命周期是动态地产生、变化和消亡的。动态性是进程最基本的特征。2)并发性。指多个进程同存于内存中能在一段时间内同时运行。引入进程的目的就是使进程能和其他进程并发执行。并发性是进程的重要特征也是操作系统的重要特征。3)独立性。指进程是一个能独立运行、独立获得资源和独立接受调度的基本单位。凡未建立PCB的程序都不能作为一个独立的单位参与运行。4)异步性。由于进程的相互制约使得进程按各自独立的、不可预知的速度向前推进。异步性会导致执行结果的不可再现性为此在操作系统中必须配置相应的进程同步机制。进程和程序的区别1.程序是一组数据指令集合存储在硬盘空间是静态的2.进程存储在内存空间执行过程需要CPU参与内存CPU3.进程具备动态生命周期从启动到消亡4.程序运行起来产生一个进程也可产生多个进程5.在一个进程中也可以执行多个程序。2.进程的创建在操作系统中终端用户登录系统、作业调度、系统提供服务、用户程序的应用请求等都会引起进程的创建。操作系统创建一个新进程的过程如下(创建原语):创建时的操作1)为新进程分配一个唯一的进程标识号并申请一个空白PCB(PCB是有限的)。若PCB申请失败则创建失败。2)为进程分配其运行所需的资源如内存、文件、I/O设备和CPU时间等(在PCB中体现)。这些资源或从操作系统获得或仅从其父进程获得。若资源不足(如内存)则并不是创建失败而是处于创建态等待内存资源。3)初始化PCB主要包括初始化标志信息、初始化CPU状态信息和初始化CPU控制信息以及设置进程的优先级等。4)若进程就绪队列能够接纳新进程则将新进程插入就绪队列等待被调度运行。./a.out ------启动进程进程在被创建的时候操作系统会为该进程分配0-4G的虚拟内存空间。3.进程的调度CPU调度进程宏观并行微观串行并发并行多个任务同时执行调度算法1.时间片轮询RR)算法时间片轮转(RR)调度算法主要适用于分时系统。这种算法最大的特点是公平系统将所有的就绪进程按FCFS策略排成一个就绪队列每隔一定的时间(如30ms)便产生一次时钟中断激活调度程序进行调度将CPU分配给就绪队列的队首进程并令其执行一个时间片。在执行完个时间片后即使进程并未运行完成它也必须释放出(被剥夺)CPU给就绪队列的新队首进程而被剥夺的进程返回到就绪队列的末尾重新排队等候再次运行。在RR调度算法中若一个时间片尚未用完而当前进程已运行完成则调度程序会被立即激活;若一个时间片用完则产生一个时钟中断由时钟中断处理程序来激活调度程序。在RR调度算法中时间片的大小对系统性能的影响很大。若时间片足够大以至于所有进程都能在一个时间片内执行完毕则时间片轮转调度算法就退化为先来先服务调度算法。若时间片很小则CPU将在进程间过于频繁地切换使CPU的开销增大而真正用于运行用户进程的时间将减少。因此时间片的大小应选择适当时间片的长短通常由以下因素确定:系统的响应时间、就绪队列中的进程数目和系统的处理能力。2.先来先服务FIFS算法在作业调度中FCFS 调度算法每次从后备作业队列中选择最先进入该队列的一个或几个作业将它们调入内存分配必要的资源创建进程并放入就绪队列。在进程调度中FCFS调度算法每次从就绪队列中选择最先进入该队列的进程将CPU分配给它使之投入运行直到运行完成或因某种原因此阻塞时才释放CPU。3.优先级调度算法在作业调度中优先级调度算法每次从后备作业队列中选择优先级最高的一个或几个作业将它们调入内存分配必要的资源创建进程并放入就绪队列。在进程调度中优先级调度算法每次从就绪队列中选择优先级最高的进程将CPU分配给它使之投入运行。根据新的更高优先级进程能否抢占正在执行的进程可将该调度算法分为如下两种:1)非抢占式优先级调度算法。当一个进程正在CPU上运行时即使有某个优先级更高的进程进入就绪队列仍让正在运行的进程继续运行直到由于其自身的原因此让出CPU时(任务完成或等待事件)才将CPU分配给就绪队列中优先级最高的进程。2)抢占式优先级调度算法。当一个进程正在CPU上运行时若有某个优先级更高的进程进入就绪队列则立即暂停正在运行的进程将CPU分配给优先级更高的进程。而根据进程创建后其优先级是否可以改变可将进程优先级分为以下两种:1)静态优先级。优先级是在创建进程时确定的且在进程的整个运行期间保持不变。确定静态优先级的主要依据有进程类型、进程对资源的要求、用户要求。优点是简单易行系统开销小;缺点是不够精确可能出现优先级低的进程长期得不到调度的情况。2)动态优先级。创建进程时先赋予进程一个优先级但优先级会随进程的推进或等待时间的增加而改变以便获得更好的调度性能。例如规定优先级随等待时间的增加而提高于是对于优先级初值较低的进程在等待足够长的时间后也可获得CPU。一般来说进程优先级的设置可以参照以下原则:1)系统进程用户进程。系统进程作为系统的管理者理应拥有更高的优先级。2)交互型进程非交互型进程(或前台进程后台进程)。大家平时在使用手机时在前台运行的正在和你交互的进程应该更快速地响应你因此自然需要被优先处理。3)I/O型进程计算型进程。所谓I/O型进程是指那些会频繁使用I/O设备的进程而计算型进程是那些频繁使用CPU的进程(很少使用I/O设备)。我们知道I/O设备(如打印机)的处理速度要比CPU慢得多因此若将I/O型进程的优先级设置得更高就更有可能让I/O设备尽早开始工作进而提升系统的整体效率。4.短作业优先SJF)调度算法短作业(进程)优先调度算法是指对短作业(进程)优先调度的算法。短作业优先(SJF)调度算法从后备队列中选择一个或几个估计运行时间最短的作业将它们调入内存运行;短进程优先(SPF)调度算法从就绪队列中选择一个估计运行时间最短的进程将CPU分配给它使之立即执行直到完成或发生某事件而阻塞时才释放CPU。例如考虑表2.2中给出的一组作业若系统采用短作业优先调度算法其平均等待时间、平均周转时间和平均带权周转时间见表2.3。SJF算法也存在不容忽视的缺点:1)该算法对长作业不利由表2.2和表2.3可知SJF调度算法中长作业的周转时间会增加。更严重的是若有一长作业进入系统的后备队列由于调度程序总是优先调度那些(即使是后进来的)短作业将导致长作业长期不被调度产生饥饿现象(注意区分死锁后者是系统环形等待前者是调度策略问题)。2)该算法完全未考虑作业的紧迫程度因此不能保证紧迫性作业会被及时处理。3)由于作业的长短是根据用户所提供的估计执行时间而定的而用户又可能有意或无意地缩短其作业的估计运行时间致使该算法不一定能真正做到短作业优先调度。SPF 算法也可以是抢占式的(若未特别说明则默认为非抢占式)。当一个新进程到达就绪队列时若其估计执行时间比当前进程的剩余时间小则立即暂停当前进程将CPU分配给新进程。因此抢占式SPF调度算法也称最短剩余时间优先调度算法。4.进程的状态普适进程状态三种基本状态linux进程状态1.运行态(用户运行态、内核运行态) R正在执行且被CPU任务调度所执行的进程2.就绪态 R正在执行没有CPU任务调度执行的进程(只缺少cpu)3.可唤醒等待态 S也称为睡眠态阻塞等待资源的进程4.不可唤醒等待态 D不想被CPU任务调度所打断的进程任务可以设置为不可唤醒等待态5.暂停态 T被暂停执行的进程6.僵尸态 Z进程执行结束空间没有被回收7.结束态 X进程执行给束空间被回收5.进程的相关命令1.ps -aux查看操作系统所有进程的相关参数PID(进程ID号、创建者、状态、CPU占有率、内存占有率。ps -aux | grep a.out将ps -aux的输出作为grep的输入查找与a.out相关的字符串| 管道将前面的输出作为后面的输入grep字符串查找2.ps -ef查看操作系统所有进程的相关参数PID进程ID),PPID(父进程ID允许一个进程创建另一个进程此时创建者称为父进程被创建的进程称为子进程。子进程可以继承父进程所拥有的资源。当子进程终止时应将其从父进程那里获得的资源还给父进程。3.top动态查看进程状态及CPU占有率内存占有率4.pstree查看进程间的创建关系(族谱图pstree -sp 进程ID查看指定ID的进程的创建关系5.killkill -信号名称/信号ID PID给PID对应的进程发送一个信号kill -l 查看系统定义出来的信号kill -9 PID 结束一个进程kill -19 PID 停止一个进程S处于可中断睡眠状态的前台进程S处于可中断睡眠状态的后台进程T处于暂停态的后台进程6.fg 后台进程编号将后台进程调到前台jobs查看当前后台进程编号6.进程相关函数fork子进程操作系统通过拷贝完整父进程0-3G内存空间数据到子进程内核空间拷贝部分内容PCB块程序执行的位置文件管理PID不拷贝PPID不拷贝注意1.进程公用3G-4G这1G的内核空间2.各自进程0-3G用户空间互相独立互不干扰不能互相通信3.进程间不能直接通信需要借助内核空间IPC机制)。pid_t fork(void)功能创建新的进程新进程叫子进程原来的进程为父进程。参数返回值成功父进程中返回子进程的PID号子进程中返回0失败-1没有新进程被创建getpid获取当前进程自己的PID号getppid获取当前进程的父进程的PID号进程的退出1.进程执行结束退出2.主函数中遇到return退出3.通过信号结束一个进程kill -9 进程ID)4.exit_exit,_Exit()结束进程也可直接结束main函数exitvoid exitint status功能退出一个进程参数status进程结束时的状态0正常退出0因为其他原因退出void _exitint status;void _Exitint status;僵尸进程与孤儿进程僵尸进程:进程已退出但其资源空间没有被其父进程回收。孤儿进程父进程先结束其父进程创建的子进程成为孤儿进程将会被系统进程所收养结束后由系统进行回收。守护进程如何避免僵尸进程产生1.由其父进程对僵尸态进程进行回收waitwaitpid2.让进程成为孤儿进程结束后由操作系统回收。wait#includesys/wait.h#includesys/types.hpid_t wait int * wstatus功能回收僵尸态进程参数wstatus接收子进程的exit中的参数指针指向的变量中的某一位接收返回值成功回收到的子进程ID号失败-1waitNULL)waitpidpid_t waitpid(pid_t pid, int *status, int options);功能:回收指定进程的资源和wait功能相似比wait更灵活参数:pid:-1回收指定进程组内的任意子进程 (-100.等待GID100的进程组中的任意子进程)-1 回收任意子进程组内外0 回收和当前调用waitpid一个组的所有子进程组内0回收指定ID的子进程status 进程退出时候的状态如果不关注退出状态用NULL;options选项:0 表示回收过程会阻塞等待WNOHANG 表示非阻塞模式回收资源。返回值:成功 返回接收资源的子进程pid失败 -1设定为非阻塞且没有回收到子进程返回0waitpid如果以阻塞方式回收和wait使用方式一样如果父进程有任务需要执行则可以选择waitpid非阻塞方式回收此时搭配轮询方式实现。7.exec函数簇作用:在一个进程里面执行外部的可执行程序(外部命令外部命令bin下的lscpmv...内部命令cd命令别名llls -l别名本质:exec将要执行的外部程序替换到了进程的文本区后面的原代码不会被执行 不会创建新进程int execl(const char* path,const char *arg,......(可省略参数)llist列表把参数列出来参数path可执行程序所在路径”/bin/ls“arg执行可执行程序时传递的参数NULL参数结束标志返回值失败-1成功不返回int execlp(const char* path,const char *arg,......(可省略参数)功能执行PATH环境变量保存的路径中的可执行程序/bin/usr/bin参数file可执行文件的名称arg执行可执行程序时传递的参数NULL: 参数的结束标志env查看系统定义出来的环境变量int execv(const char* path, char *const argv[ ])将参数用argv数组保存int execvp(const char* path, char *const argv[ ])结合execlp与execv自动去/bin下找path同时argv保存参数二.线程1.线程线程最直接的理解就是轻量级进程它是一个基本的CPU执行单元也是程序执行流的最小单元由线程ID、程序计数器、寄存器集合和堆栈组成。线程是进程中的一个实体是被系统独立调度和分派的基本单位线程自己不拥有系统资源只拥有一点儿在运行中必不可少的资源但它可与同属一个进程的其他线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程同一进程中的多个线程之间可以并发执行。由于线程之间相互制约致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。线程是操作系统任务调度的最小单位。进程是操作系统资源分配的最小单位。2.线程的创建线程由所在进程创建线程一定是属于某个进程的。线程创建时所在进程为其分配独立的栈区空间默认8M线程共用所在进程的堆区、数据区、文本区、内核区域。3.进程与线程的区别进程线程概念操作系统资源分配的最小单位CPU任务调度的最小单位效率操作系统要为进程分配0-4G虚拟内存空间线程创建比进程快只需要分配栈区线程间任务切换速度快系统开销小内存内存消耗大相同资源环境下并发量比线程小只需要独立的栈区空间其他空间和进程共享安全性各进程空间独立安全性高公用空间没有进程安全性高通信进程不能直接通信需要使用IPC机制通信线程间可以直接通信全局变量、全局队列4.线程的调度宏观并行微观串行调度方式与进程一样5.线程消亡1.线程退出2.回收线程资源空间6.线程相关函数接口int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);功能创建并启动一个线程参数thread 保存线程ID的变量地址attr 线程属性的变量地址NULL 按照默认属性创建start_routine函数指针指向线程执行的任务函数的指针线程任务函数arg 传递给线程任务函数的参数返回值成功0失败错误码!0注意1. 使用线程相关接口时编译和链接需要链接线程库-lpthread/-pthread。2. 创建线程的主进程不能先于线程结束。