首页 > 系统相关 >5.进程线程模型你知道多少?

5.进程线程模型你知道多少?

时间:2023-09-16 19:22:26浏览次数:43  
标签:int 模型 exit pthread 进程 线程 void

5.进程线程模型你知道多少?

1.进程


  1. 进程创建与结束

    • 背景知识:

      进程有两种创建方式,一种是操作系统创建的一种是父进程创建的。从计算机启动到终端执行程序的过程为:0号进程 -> 1号内核进程 -> 1号用户进程(init进程) -> getty进程 -> shell进程 -> 命令行执行进程。所以我们在命令行中通过 ./program执行可执行文件时,所有创建的进程都是shell进程的子进程,这也就是为什么shell一关闭,在shell中执行的进程都自动被关闭的原因。从shell进程到创建其他子进程需要通过以下接口。

    • 相关接口:

      • 创建进程:pid_t fork(void);

        返回值:出错返回-1;父进程中返回pid > 0;子进程中pid == 0

      • 结束进程:void exit(int status);

        • status是退出状态,保存在全局变量中S?,通常0表示正常退出。
      • 获得PID:pid_t getpid(void);

        返回调用者pid。

      • 获得父进程PID:pid_t getppid(void);

        返回父进程pid。

    • 其他补充:

      • 正常退出方式:exit()、_exit()、return(在main中)。

        exit()和_exit()区别:exit()是对__exit()的封装,都会终止进程并做相关收尾工作,最主要的区别是_exit()函数关闭全部描述符和清理函数后不会刷新流,但是exit()会在调用_exit()函数前刷新数据流。

        return和exit()区别:exit()是函数,但有参数,执行完之后控制权交给系统。return若是在调用函数中,执行完之后控制权交给调用进程,若是在main函数中,控制权交给系统。

      • 异常退出方式:abort()、终止信号。

  2. Linux进程控制

  • 进程地址空间(地址空间)

    虚拟存储器为每个进程提供了独占系统地址空间的假象。

    尽管每个进程地址空间内容不尽相同,但是他们的都有相似的结构。X86 Linux进程的地址空间底部是保留给用户程序的,包括文本、数据、堆、栈等,其中文本区和数据区是通过存储器映射方式将磁盘中可执行文件的相应段映射至虚拟存储器地址空间中。

    有一些"敏感"的地址需要注意下,对于32位进程来说,代码段从0x08048000开始。从0xC0000000开始到0xFFFFFFFF是内核地址空间,通常情况下代码运行在用户态(使用0x00000000 ~ 0xC00000000的用户地址空间),当发生系统调用、进程切换等操作时CPU控制寄存器设置模式位,进入内和模式,在该状态(超级用户模式)下进程可以访问全部存储器位置和执行全部指令。

    也就说32位进程的地址空间都是4G,但用户态下只能访问低3G的地址空间,若要访问3G ~ 4G的地址空间则只有进入内核态才行。

  • 进程控制块(处理机)

    进程的调度实际就是内核选择相应的进程控制块,被选择的进程控制块中包含了一个进程基本的信息。

  • 上下文切换

    内核管理所有进程控制块,而进程控制块记录了进程全部状态信息。每一次进程调度就是一次上下文切换,所谓的上下文本质上就是当前运行状态,主要包括通用寄存器、浮点寄存器、状态寄存器、程序计数器、用户栈和内核数据结构(页表、进程表、文件表)等。

    进程执行时刻,内核可以决定抢占当前进程并开始新的进程,这个过程由内核调度器完成,当调度器选择了某个进程时称为该进程被调度,该过程通过上下文切换来改变当前状态。

    一次完整的上下文切换通常是进程原先运行于用户态,之后因系统调用或时间片到切换到内核态执行内核指令,完成上下文切换后回到用户态,此时已经切换到进程B。

2.线程

对于线程,我认为弄清以下两点非常重要:

  • 线程之间有无先后访问顺序(线程依赖关系)
  • 多个线程共享访问同一变量(同步互斥问题)
  1. 线程创建和结束

    • 背景知识:

      在一个文件内的多个函数通常都是按照main函数中出现的顺序来执行,但是在分时系统下,我们可以让每个函数都作为一个逻辑流并发执行,最简单的方式就是采用多线程策略。在main函数中调用多线程接口创建线程,每个线程对应特定的函数(操作),这样就可以不按照main函数中各个函数出现的顺序来执行,避免了忙等的情况。线程基本操作的接口如下。

    • 相关接口:

      • 创建线程:int pthread_create(pthread_t *tidp,const pthread_attr_t attr, void (start_rtn)(void),void *arg);

        创建一个新线程,pthread和start_routine不可或缺,分别用于标识线程和执行体入口,其他可以填NULL。

        • pthread:用来返回线程的tid,*pthread值即为tid,类型pthread_t == unsigned long int。
        • attr:指向线程属性结构体的指针,用于改变所创线程的属性,填NULL使用默认值。
        • start_routine:线程执行函数的首地址,传入函数指针。
        • arg:通过地址传递来传递函数参数,这里是无符号类型指针,可以传任意类型变量的地址,在被传入函数中先强制类型转换成所需类型即可。
      • 获得线程ID:pthread_t pthread_self();

        调用时,会打印线程ID。

      • 等待线程结束:int pthread_join(pthread_t tid, void** retval);

        主线程调用,等待子线程退出并回收其资源,类似于进程中wait/waitpid回收僵尸进程,调用pthread_join的线程会被阻塞。

        • tid:创建线程时通过指针得到tid值。
        • retval:指向返回值的指针。
      • 结束线程:pthread_exit(void *retval);

        子线程执行,用来结束当前线程并通过retval传递返回值,该返回值可通过pthread_join获得。

        • retval:同上。
      • 分离线程:int pthread_detach(pthread_t tid);

        主线程、子线程均可调用。主线程中pthread_detach(tid),子线程中pthread_detach(pthread_self()),调用后和主线程分离,子线程结束时自己立即回收资源。

        • tid:同上。
  2. 线程属性值修改

    • 背景知识:

      线程属性对象类型为pthread_attr_t,结构体定义如下:

typedef struct{
    int detachstate;    // 线程分离的状态
    int schedpolicy;    // 线程调度策略
    struct sched_param schedparam;    // 线程的调度参数
    int inheritsched;    // 线程的继承性
    int scope;    // 线程的作用域
    // 以下为线程栈的设置
    size_t guardsize;    // 线程栈末尾警戒缓冲大小
    int stackaddr_set;    // 线程的栈设置
    void *    stackaddr;    // 线程栈的位置
    size_t stacksize;    // 线程栈大小
}pthread_attr_t;
  • 相关接口:

    对上述结构体中各参数大多有:pthread_attr_get()和pthread_attr_set()系统调用函数来设置和获取。这里不一一罗列。

标签:int,模型,exit,pthread,进程,线程,void
From: https://www.cnblogs.com/codemagiciant/p/17707152.html

相关文章

  • springmvc接收请求是每一个请求都会新开一个线程吗?——不,是线程复用
    答案是否定的这是我学习苍穹外卖时候测出来的,发现springmvc接收请求会复用线程,跟用的ThreadLocal工具类有冲突,因为用完后不会清除掉ThreadLocal中存储的值导致微信回调的支付方法使用了管理端的id,导致空指针异常。主要还是要注意springmvc接收请求是线程复用的就行了。......
  • 线程休眠
      在主线程中控制其他线程的休眠的方法: ......
  • 获得当前线程对象
     Thread.currentThread()在哪个线程中调用这个方法就返回哪个线程自身的对象引用 应用: ......
  • 获取和设置线程名字
     线程有默认名字,第一个线程编号默认为0 ......
  • 深度学习模型压缩方法概述
    一,模型压缩技术概述知识蒸馏算法整体的框架图如图下所示。图片来源https://intellabs.github.io/distiller/knowledge_distillation.html。三,轻量级模型架构四,模型剪枝模型剪枝(modelpruning)也叫模型稀疏化(modelsparsity)。深度学习模型中一般存在着大量冗余的参数,将权重矩阵中......
  • Win32编程之线程开发(八)
    一、线程概念(1).Windows线程是可以执行的代码的实例,系统是以线程为单位调度程序,一个程序当中可以有多个线程,实现多任务的处理(2).Windows线程的特点:线程都具有一个ID每个线程都具有自己的内存栈同一进程中的线程使用同一个地址空间(3).线程的调度:操作系统将CPU的执行时间......
  • 相机成像模型
    详细推导了相机成像模型。小孔成像小孔成像是初中物理知识,如图所示,蜡烛发出的光线经过小孔投射在光屏上呈现出倒立的实像。以上成像过程涉及三个重要对象,即物点(蜡烛本身)、光心(小孔)、像点(光屏上的亮点),三者连起来的直线叫做光路。小孔成像是理想条件下的相机成像模型。......
  • MVP模型
    MVP模型:1.概念:MVP是一种敏捷模型,精益创业术语"最小可行产品"(MinimumViabeProduct)的简称.用最快、最简明的方式建立一个可用的产品模型,推向市场,测试用户是否喜欢这个产品,进而迭代完善细节.利用MVP模型,可以低成本试错和反复的成本.2.注意事项:不能成为产品定位不清晰、......
  • 如何成功将 API 客户的 transformer 模型推理速度加快 100 倍
    ......
  • CompletableFuture 异步多线程D优雅!
    一个示例回顾Future一些业务场景我们需要使用多线程异步执行任务,加快任务执行速度。JDK5新增了Future接口,用于描述一个异步计算的结果。虽然Future以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,我们必须使用Future.get()的方式阻塞调用线程,或者使用轮......