进程线程及其状态

进程线程及其状态

进程

进程的概念

  • 进程就是执行中的程序。

进程的状态

进程有五种状态,分别是:

  • 新建:进程正在被创建
  • 运行:进程正在被执行
  • 阻塞:进程等待某个事件(如I/O操作)
  • 就绪:进程等待分配处理器
  • 终止:进程完成执行

进程调度流程图

线程

线程的概念

  • 线程是程序执行流的最小单元,线程早期也有轻量级进程之称。一个进程中可能包含多个线程。在系统内核层面,进程与线程并无本质的不同。进程与线程最大的不同点是资源分配。

线程与进程的比较

  • 线程与进程都可以实现多任务。
  • 线程是CPU调度的基本单元,进程是系统资源分配的基本单元。
  • windows下进程线程是泾渭分明,区别明显的。在Linux中它们有很多共同特性。
  • 在早期Linux的内核结构中:进程和线程的区别只是创建子进程和子线程时,是否设置为共享内存,二者在内核中的存储结构并无区别,系统调度的单位也是轻量级进程。2.6以后的Linux内核版本才将线程和进程完全独立开来。
  • 线程的状态改变只代表了CPU执行过程的改变,线程操作的资源仍然是进程的。除了 CPU外,计算机内的软硬件资源的分配都是以进程为单位的。进程拥有一个完整的虚拟地址空间,不依赖于线程而独立存在,而线程只是进程的一部分,与进程内的其他线程一起共享分配给该进程的所有资源。

线程的状态

  • 同进程的实现原理类似,线程也可主要概括为五种状态(实际上Linux将线程状态细分为十几种):

    • 新建,由于不需要进行必要的内存复制等工作,新建线程要比新建进程更快。
    • 就绪
    • 运行
    • 阻塞
    • 死亡,线程死亡后,也需要回收处理。
  • 调度的过程参考进程。

线程的内核调度

  • 多线程编程具有响应度高、资源共享、经济和多处理器体系结构的利用四个优点。用户线程是映射到内核线程池进行CPU调度的,映射关系模型包含有:

    • (1)多对一
    • (2)一对一
    • (3)多对多

内核调度图

  • 这里为什么没有一对多?因为线程是CPU资源调度的最小单位,即:单线程在一个时间点上只能利用到一个核心(进行一个原子操作),一个原子操作不能再分开由不同核心执行。而多核CPU在执行单线程任务时,可能会切换多个核心轮流来执行这个任务(每个原子操作的CPU核心可能并不相同),例如在执行循环时,这次循环和下次循环可能并不是同一个核心来执行的(这跟你的系统有关,但可以看到单线程最多只能占用到 (1/CPU核心数) 的CPU资源(超线程CPU占用1/(CPU线程数))。
  • 而资源上,多核CPU调用同一资源时,X86架构会使用总线锁,对该资源进行锁定,保证原子操作执行完整不被打断。当操作完成时,会解锁并通知其他线程,我操作完了,你们可以来操作了(实际上,此方法效率很低,仅作为最后一道保险)。
  • 因此确定一个操作是原子操作时,没有必要浪费外围昂贵的开销再来给他加锁,原子操作本身就是一道互斥锁。互斥锁的目的,也正是将一系列操作变为原子操作。

进程的诞生与消亡

  • 进程的诞生

    • (1)fork函数:子进程拷贝父进程的数据(具体实现是读时共享,写时复制)
    • (2)vfork函数:子进程与父进程共享数据
    • vfork是一个过时的函数,虽然与fork相比有那么一点性能优势,但其带来一连串的坑并不那么好填,不建议使用,除非你对性能追求到极致。
  • 进程的消亡
    • (1)正常结束和异常终止;
    • (2)linux系统设计时规定:每个进程结束时,系统会自动回收open但没有close的文件资源,malloc但没有free的资源等,但并不会回收进程本身占用的资源(即进程的尸体,主要包括进程本身的文件描述符对应的资源(task_struct结构体)和进程的栈空间),这需要由进程的父进程来完成回收(收尸)。
  • 僵尸进程
    • 在上述(2)中,如果父进程没有结束,而且也不回收已结束的子进程(收尸),已经结束的子进程,就变成了僵尸进程。
    • 父进程可以使用wait或waitpid,显式地回收子进程(剩余待回收)的内存资源并且获取子进程退出状态。
    • 父进程结束时也会自动回收僵尸进程,但应避免这种不严谨的方式。
  • 孤儿进程
    • 子进程还在执行,而父进程先结束了,子进程就成为了孤儿进程,托管到系统了。
    • 此时子进程的父进程变为了系统的init进程,init进程会在孤儿进程结束后自动回收孤儿进程的资源。

线程的诞生与消亡

  • 线程标识(线程ID)

    • 进程ID在整个系统中是唯一的。
    • 线程ID(pthread_t类型)只在它所属的进程中有效。
    • pthread_t(Linux中为unsigned int类型,OS中为结构体指针,Windows中为handle句柄)用于声明线程ID。
    • 函数:pthread_self取得自身线程ID。
  • 创建线程
    • 使用函数pthread_create,线程创建后,就开始运行相关的线程函数。
  • 退出线程。
    • 线程执行完毕。可以return,不能exit(exit是退出进程)。
    • 使用函数pthread_exit,主动退出线程。主线程使用该函数时,进程并不会结束,而是等待其他线程结束。
    • 进程结束时,线程也结束(线程依赖于其所在的进程)。
  • 线程回收
    • 由于线程使用的资源是属于进程的,退出线程而进程仍然运行时资源并未完全释放,形成僵尸线程。
    • pthread_join(tid)函数类似wait/waitpid函数,用于阻塞等待线程tid结束,调用它的线程一直等待到tid线程结束时,tid线程资源就被回收。
    • pthread_detach(tid)函数线程分离,让系统自动回收tid线程。
    • 按以下步骤回收:
      • pthread_attr_t attr;//线程创建前,定义线程属性
      • pthread_attr_init(&attr);//进行初始化线程属性
      • pthread_attr_getdetachsate(&attr,&status);//获取分离状态
      • pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);//设置线程分离状态.
      • pthread_create(&tid, &attr,func,NULL);//创建线程
      • pthread_attr_destroy(&attr);//线程结束时,调用回收函数
    • 线程回收代码示例:
    void * func(void *p)
    {
        printf("我是子线程\n");
    }
    int main(int argc, char *argv[])
    {
        pthread_attr_t attr; //定义一个变量
        pthread_t tid;
        pthread_attr_init(&attr);//初始化
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//设置分离
        pthread_create(&tid, &attr, func, NULL);//创建线程
        sleep(1);//等1秒让子线程执行完
        pthread_attr_destroy(&attr);//释放
        return 0;
    }

原文地址:https://www.cnblogs.com/yanlei2018/p/8168034.html

时间: 2024-08-29 07:35:45

进程线程及其状态的相关文章

001-多线程基础-进程线程、线程状态、优先级、用户线程和守护线程

一.进程与线程 1.DOS系统[单进程系统] 最早的时候DOS有一个特点:只要电脑有病毒,那么电脑就死机了. 原因:传统的DOS系统属于单进程系统,即:在同一时间段内只允许有一个程序运行. 2.Windows系统[多进程多线程] 电脑中毒也可以运行,但是会变慢 原因:因为在一个cpu.一块资源的情况下,程序利用一些轮转算法,可以让一个资源在一个时间段可以同时处理多个程序(进程),但是在一个时间点上只允许一个进程去执行. windows:任务管理器 linux:ps 在每一个进程上可以划分出若干个

【学习总结】【多线程】 安全隐患 & 通讯 & 线程的状态

一.多线程的安全隐患 资源共享 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源 比如多个线程访问同一个对象.同一个变量.同一个文件 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题 所以很自然的,当某个线程进入某个事件,处理某个事件,访问某个对象的时候,先加 “锁” 互斥锁的优缺点 优点:能有效防止因多线程抢夺资源造成的数据安全问题 缺点:需要消耗大量的CPU资源 互斥锁的使用前提:多条线程抢夺同一块资源 相关专业术语:线程同步,多条线程按顺序地执行任务 互斥锁,就

Linux下进程线程,Nignx与php-fpm的进程线程方式

1.进程与线程区别 进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集.从内核的观点看,进程的目的就是担当分配系统资源(CPU时间.内存等)的基本单位. 线程是进程的一个执行流,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.一个进程由几个线程组成(拥有很多相对独立的执行流的用户程序共享应用程序的大部分数据结构),线程与同属一个进程的其他的线程共享进程所拥有的全部资源. "进程——资源分配的最小单位,线程——程序执行的最小单位" 进程有独立的地

线程的状态以及相关的操作方法

线程的状态:创建线程Thread name =  new Thread() 就绪状态 运行状态 堵塞状态 死亡状态 线程的操作:1.在Thread类中可以通过getName()和setName()方法设置线程的名称,尽量避免名称的重复出现.要是在线程的操作过程中没有给线程一个名称,则在系统使用时会为线程分配一个名称,Thread-XX.并在其中Thread类中存在一个static属性. 1 package Rubbableclass; 2 class MyThread implements Ru

进程/线程介绍

一.进程 进程可以认为是程序执行时的一个实例.进程是系统进行资源分配的独立的实体,且每个进程拥有独立 的地址空间.一个进程无法直接访问另一个进程的变量和数据结构,如果希望让一个进程访问另一个进程 的资源,需要使用进程间通信,比如:管道,有名管道,信号,信号量,消息队列,套接字等. 一个进程可以拥有多个线程,每个线程使用其所属进程的栈空间.线程和进程的一个主要区别是,同一程序内 的多个线程会共享部分状态,多个线程可以读写同一块内存(一个进程无法直接访问另一进程的内存).同时 每个线程还拥有自己的寄

进程线程协程那些事儿

一.进程与线程 1.进程 我们电脑的应用程序,都是进程,假设我们用的电脑是单核的,cpu同时只能执行一个进程.当程序出于I/O阻塞的时候,CPU如果和程序一起等待,那就太浪费了,cpu会去执行其他的程序,此时就涉及到切换,切换前要保存上一个程序运行的状态,才能恢复,所以就需要有个东西来记录这个东西,就可以引出进程的概念了. 进程就是一个程序在一个数据集上的一次动态执行过程.进程由程序,数据集,进程控制块三部分组成.程序用来描述进程哪些功能以及如何完成:数据集是程序执行过程中所使用的资源:进程控制

9 异常处理 操作系统 进程线程 队列+生产消费者模型 进程同步 回调函数

异常处理 异常就是程序运行时发生错误的信号,在python中,错误触发的异常如下 异常的种类: AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常:基本上是无法打开文件 ImportError 无法引入模块或包:基本上是路径问题或名称错误 IndentationError 语法错误(的子类) :代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访

操作系统:进程/线程同步的方式和机制,进程间通信

一.进程/线程间同步机制. 临界区.互斥区.事件.信号量四种方式临界区(Critical Section).互斥量(Mutex).信号量(Semaphore).事件(Event)的区别1.临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问.在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问公共资源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占.2.互斥量:采用互斥对象机

python进程线程

一.背景知识 理论基础 1.操作系统的作用: (1)隐藏丑陋复杂的硬件接口,提供良好的抽象接口 (2)管理.调度进程,并且将多个进程对硬件的竞争变得有序 2.多道技术: (1)产生背景:针对单核,实现并发(现在的主机一般是多核,name每个核都会利用多道技术,但是核与核之间没有使用多道技术切换这么一说,一个程序IO阻塞,会等到IO结束再重新调度) (2)时间上的复用(复用一个cpu的时间片)+空间上的复用(如内存中同时有多道程序) 二.进程 1.什么是进程 进程:正在进行的一个过程或者说一个任务