进程和线程

        进程是操作系统中程序执行的基本单位。一个进程包括了多个组成部分,主要可以分为以下几个方面:1. 程序代码:•进程包含了一段可执行的程序代码,也就是实际执行的指令序列。2. 进程控制块 (PCB):•PCB 是操作系统用来管理进程的数据结构,包含了操作系统控制和管理进程所需的所有信息。•PCB 包括的信息通常有: •进程标识符(PID)•进程状态(运行、就绪、阻塞等)•CPU 寄存器的值(包括程序计数器 PC)•内存管理信息(如页表)•访问权限•等待的资源和条件变量•优先级•父进程和子进程的链接•时间片•I/O 状态信息3. 内存空间:•进程有自己的私有内存空间,包括: •代码段:存放程序的机器指令。•数据段:存放程序的全局变量和静态变量。•堆:动态分配的内存区域。•栈:用于函数调用时的局部变量和函数参数。4. 打开的文件描述符:•进程可以打开文件和其他 I/O 资源,每个打开的资源都有一个文件描述符。•文件描述符是用于标识这些资源的小整数。5. 环境变量:•进程可以拥有自己的环境变量集,这些变量通常用于配置程序的行为。6. 资源:•进程可以占用系统资源,如 CPU 时间、内存、磁盘空间等。7. 线程:•多线程进程中的每个线程都是进程的一部分,共享进程的大部分资源,但有自己的栈空间和寄存器状态。进程的状态进程的状态通常包括:•运行:进程正在 CPU 上执行。•就绪:进程准备好执行,但等待 CPU 时间片。•阻塞:进程因等待某种事件(如 I/O 操作完成)而暂时不能执行。进程的生命周期进程通常经历以下阶段:1. 创建:当一个程序启动时,操作系统创建一个新的进程。2. 执行:进程在其生命周期内执行程序代码。3. 结束:进程完成其任务或遇到错误时终止

        线程是操作系统中程序执行的基本单位之一,它是进程内的一个执行实体。一个线程通常包括以下几个组成部分:1. 线程标识符 (TID):•每个线程都有一个唯一的标识符,称为线程 ID (TID),用于区分同一进程中的不同线程。2. 线程控制块 (TCB):•TCB 是操作系统用来管理线程的数据结构,包含了操作系统控制和管理线程所需的所有信息。•TCB 包括的信息通常有: •线程状态(运行、就绪、阻塞等)•CPU 寄存器的值(包括程序计数器 PC)•栈指针•优先级•等待的资源和条件变量•线程间通信的信息3. 栈空间:•每个线程都有自己的独立栈空间,用于存储函数调用时的局部变量和函数参数。4. CPU 寄存器状态:•线程在执行时,会使用 CPU 的寄存器。当线程被切换时,这些寄存器的值会被保存在线程的 TCB 中。5. 线程局部存储 (TLS):•TLS 是一种特殊的存储区域,其中的变量只能被同一个线程访问。6. 资源引用:•线程可以持有对资源的引用,如文件描述符、互斥锁等。线程与进程的关系线程与进程的主要区别在于它们如何共享资源:•共享资源:•线程通常共享同一进程中的大部分资源,如内存空间、打开的文件描述符、环境变量等。•这意味着一个线程可以访问另一个线程的全局变量和静态变量。•独立状态:•每个线程都有自己的栈空间和寄存器状态,这意味着线程之间可以独立执行。•调度和切换:•线程间的切换通常比进程间的切换开销小,因为线程共享大部分资源,不需要切换地址空间。线程的状态线程的状态通常包括:•运行:线程正在 CPU 上执行。•就绪:线程准备好执行,但等待 CPU 时间片。•阻塞:线程因等待某种事件(如 I/O 操作完成或等待互斥锁)而暂时不能执行。线程的生命周期线程通常经历以下阶段:1. 创建:当一个进程启动时,最初只有一个主线程。可以通过创建新的线程来扩展并发能力。2. 执行:线程在其生命周期内执行程序代码。3. 结束:线程完成其任务或遇到错误时终止。总结

进程线程

1.进程的概念 
2.进程 和 程序
 将 存放 硬盘中程序 ,加载到内存中,运行起来,就是进程
 eg:
    QQ 

3.进程的组成
 
 进程 = PCB + text|data|bss|堆栈 
 
 
 PCB  --- 操作系统 Process control block 
         struct task_struct
        {
           ....
        }         
 //宏观并行
 //微观串行 
 
4.进程的状态  //伴随进程的生命周期 
  三态模型  (就绪态 -- 执行态 --阻塞态) 
  linux操作系统 (R-S-D-T-Z)
 
  命令 
  top
  ps -elf | grep a.out 
  ps aux |grep a.out 
  pstree -sp pid号 
  kill 
  killall 

5.创建进程  //编程 

  fork 
  复制 // 
  
  注意:
  1.fork之后,父进程与子进程 都是从fork下一话话开始执行 //pc (Program Counter)
  2.fork之后,返回值 
    父子进程,各自返回了一次 
  3.fork之后,父子进程运行顺序 
    取决于 操作系统调度 
  4.fork之后,父子进程 各自拥有独立的4g内存空间 
    父进程和子进程之间数据不共享,独立的。
  
  5.fork之后,程序处理的逻辑 
   
   //父进程 原本独立要运行的代码
   pid = fork();
   //都可以执行到的部分  
   if (pid >0)
    {
      //父进程 
    }else if (pid == 0)
    {
     
    }
    //都会执行的部分 
    
6.进程的执行 
  a.子进程做与父进程相同的事情 --- 创建子进程 执行任务即可 
  b.子进程做与父进程不同的事情 --- fork+exec
                                   
                                
 exec 
 l vs  v  //主要是第二个参数 的传参方式不同 
 p        //表示寻找可以执行文件 是通过PATH环境变量
 e        //e表示可以给要执行的程序,传递一个环境变量 

7.回顾 
//1.创建进程 -- fork  
//2.进行的执行 
  a.子进程与父进程做相同的时间 
    eg: 12306 淘宝
  b.子进程做的事情与父进程不相同 
    eg: shell    
       //shell --- fork --shell+exec
       
    exec函数族  //启动一个新的程序 
    execl
    execv    //"~"  /home/linux 
    execlp
    execvp 
    execle
    execvpe     
//3.进程退出 
  两大类:
  正常退出 
  a.return 从main函数
  b.exit  
    atexit // 注册 "退出清理函数" 的函数    
    IO缓冲清理 
  c._exit 
  异常退出 ---信号结束掉 
  abort 
  signal 
//4.wait  
wait //功能:
     //1.获取子进程退出状态 
     //2.回收资源    //会让僵尸态的子进程销毁 
注:
  1.wait的本身 是一个 阻塞操作 
    会使调用者 阻塞 
  2.父进程要获得子进程的退出状态 
    子进程
       exit(退出状态值)
       退出状态值 只有最低8位有效 [0~255]
    父进程
      wait(&status)
      获取到退出状态值
      WIFEXITED() //先判断是否为正常退出
      WEXITSTATUS() //获取到exit传递的退出状态值
      
练习:
     举例:
   无人机 
      
   1.控制模块 
   2.视频模块 
   3.传输模块 
   4.存储模块 
   
   
pid_t waitpid(pid_t pid, int *wstatus, int options);
功能:
     等待子进程状态发生变化 
参数:
   @pid 
        pid = -1  //表示等待所有子进程    
        pid > 0   //表示等待 指定的子进程状态改变 
   eg:
      100   //表示等待pid号为100的子进程状态改变 
  @wstatus  //表示获取到 子进程 状态信息 
  @options  //选项 
            //可以不阻塞  WNOHANG  //hang on   
            //默认是阻塞  0 
            
  wait(&wstatus) <=> waipid(-1,&wstatus,0)
   
     
  非阻塞调用:
  
  waitpid(-1,&wstatus,WNOHANG); //表示非阻塞调用 
  
  非阻塞 和 阻塞 
  1.阻塞 
       会父进程处理逻辑 
  2.非阻塞 
       父进程 会去查看 子进程状态改变
       但是,如果没有发生改变,父进程不阻塞,
       整个程序继续往下 
       非阻塞 必须 套在循环中处理  //轮询 
       
总结:
   1.wait 和 waitpid都是 等待子进程状态改变 
   2.wait 是一种阻塞调用
   3.waitpid 可以实现非阻塞调用 
   
  进程退出:
  处理方式 
  wait        //阻塞方式 --- 调用进程 一般不做额外的事情 
  waitpid     //非阻塞的方式 --- 调用进程 逻辑一般不受影响
                                waitpid 想要处理到子进程
                                必须套在循环中

                                
练习:
    创建3个子进程 
    子进程打印 自己的pid号之后,退出 
    父进程 回收 第二个子进程 
      //waitpid  //回收指定的子进程 
    
---------------------------------------------------------
1.创建 ---fork  
          //创建一个子进程 
          //创建多个子进程 
          //创建好之后,能区分父子进程代码的逻辑 
2.执行 
  a.做与父进程相同的事情 
  b.做与父进程不同的事情
    fork + exec //minishell 
3.进程的退出
  return 
  exit
  _exit
//atexit  
4.两个特殊状态 
  孤儿进程 --- 没有危害 ,不需要处理 
  僵尸态进程 --- 处理 
  wait 
  waitpid
---------------------------------------------------------
多任务的技术: 线程 
1.什么是线程 
  线程 --轻量级的进程 
         light weight 

2.为什么需要线程?
  
  进程的产生  ----- fork

  线程 --- 轻量级的进程  
  进程 --- 重量级的进程 
  
  线程 成为 CPU执行的最小单位 
  进程 成为 资源分配的基本单位 

  线程 
     创建 和 调度 时空开销都比进程小   

3. 线程组成
   线程tid //thread 
   程序计数器 
   寄存器集合
   栈 
4. 线程与进程的关系
  a.线程 是 存在于 进程中的 
  b.线程 共享了进程的资源 (代码段,数据段,打开一些文件,信号等)
  c.线程结束,不一定导致进程结束 
  
5.线程的编程 
  类似与进程过程 
  
  线程函数 
  Red hat / IBM
         //thinkpad   
  ubuntu 
  contos //服务器上 --- linux系统运维 
  
  red hat 实现的一套线程函数 //NPTL线程库
  NPTL (New Posix Thread Library) 
  
  a.线程的创建  pthread_create  
  
  int pthread_create(pthread_t *thread, 
             const pthread_attr_t *attr,
             void *(*start_routine) (void *),
             void *arg);

   功能:该函数可以创建指定的一个线程。
    参数:
         @thread 线程id,需要实现定义并由该函数返回。
         @attr   线程属性,一般是NULL,表示默认属性。(可结合性+分离属性)
                 默认(可结合性) -- 自己手动回收
                 分离属性       -- 系统自动回收 
        @start_routine  -- 线程执行函数 (线程回调函数)
                //指向[指针函数的] 函数指针。
                  本质上是一个函数的名称即可。
                称为
                  th 回调函数,是线程的执行空间。
                  {
                  }
                //注: 线程回调函数 --完成线程任务功能的函数 
                //    需要调用者 自己实现
        @arg  回调函数的参数,即参数3的指针函数参数。
    返回值:成功 0
            失败 错误码             
    

练习:
     创建两个线程 
     要求,两个线程,打印不一样内容 

注:
   1. 主函数所在的执行流 --- 主线程 
   2. 其它的线程   ---  子线程(次线程)   
   3. 各个线程间 低位是平等  //对等 

   
获得线程tid:
 pthread_self(); //在那个线程中调用,获得的就是那个线程的tid 
 
 
 练习:
     主函数中定义一个 栈上的变量
     int a=1;     
     创建两个线程 
     线程1 对 a 加1 
     线程2 对 a 加2 
     
 
 练习:
    定义一个全局变量 
     int a=1;     
     创建两个线程 
     线程1 对 a 加1 
     线程2 对 a 加2 
 
 
 
  b.线程的执行   --- 就体现在线程的 执行函数(回调函数)上
  c.线程的退出
  
  方式1 
     pthread_exit 
      
    void pthread_exit(void *retval)
    功能:
         结束调用的线程 
    参数:
       @retval  //退出状态值  //传的是,退出状态值 对应的地址 
      
    注意:
      1.pthread_exit 本身表示结束线程 
        如果用在main函数中 表示结束主线程 
        主线程结束 并不表示进程 
        此时,
        主线程执行流结束,进程会在其余线程都结束后,结束 
        
      
  d.线程的资源回收 
  int pthread_join(pthread_t thread, void **retval);
  功能:
       等待线程结束 
  参数:
     @thread  --- 线程tid  
     @retval  --- 用来保存,退出状态值,所在空间的地址 
     
 返回值:
    成功 0
    失败 错误码 
  注:
     线程退出时,可以带出退出状态值,
     但是传的是,退出状态值对应空间的地址
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值