• C/C++进程线程超详细详解


    目录

    前言

    一、进程基础

    1.进程概念

    2.进程特征

    3.进程状态(如图清晰可见)

    4,进程的标识

    实例代码如下:

    5.进程的种类

    实例shell脚本程序如下:

    二、进程API

    1.创建子进程

    实例代码如下:

    2.exec函数族

     函数族讲解图如下所示:

    实例代码如下所示: 

    3.结束进程

    实例代码如下所示:

    4.给进程收尸(释放进程占用的资源)

     wait实例代码如下:

    waitpid实例代码如下: 

    总结


    前言

    进程和线程的广泛意义是什么?

    进程是计算机中运行的程序的实例。它具有独立的内存空间和资源,是操作系统分配和管理资源的基本单位。每个进程都拥有独立的地址空间、全局变量和文件打开等资源,进程之间相互独立。进程之间通常通过进程间通信(IPC)机制进行数据交互。

    线程是进程中的一个执行单元。一个进程可以包含多个线程,这些线程共享进程的地址空间和资源,可以同时执行不同的代码路径。线程之间可以通过共享内存进行数据交换,因为它们可以访问相同的全局变量和堆内存。


    一、进程基础

    1.进程概念

    进程是一个独立的可调度的任务
        (1)进程是一个抽象实体。当系统在执行某个程序时,分配和释放的各种资源
        (2)进程是一个程序的一次执行的过程
    进程和程序的区别
        程序是静态的,它是一些保存在磁盘上的指令的有序集合,没有任何执行的概念
        进程是一个动态的概念,它是程序执行的过程,包括创建、调度和消亡
        进程是程序执行和资源管理的最小单位

    2.进程特征

    动态性 ----程序一次运行过程
    并发性 ----可以同时运行多个进程
    独立性 ----每个进程在各自独立的虚拟内存中运行
    异步性 ----多个运行的进程之间相互没有关系

    3.进程状态(如图清晰可见)

    4,进程的标识

    (1)主要的进程标识
        进程号(Process Identity Number,PID)
        父进程号(Parent Process ID,PPID)
        
    (2)PID唯一地标识一个进程。可以通过以下两个函数获得:
        pid_t getpid(void)     //获取进程ID
        pit_t getppid(void)    //获取父进程ID

    实例代码如下:

    1. int main(void)
    2. {
    3. printf("pid = %d\n",getpid());
    4. printf("ppid = %d\n",getppid());
    5. return 0;
    6. }

     在终端运行的结果以及ps命令作用结果如下:

    5.进程的种类

    (1)交互进程:
        该类进程是由shell控制和运行的。交互进程既可以在前台运行,也可以在后台运行。
        
    (2)批处理进程:
        该类进程不属于某个终端,它被提交到一个队列中以便顺序执行。

    实例shell脚本程序如下:

            终端输入命令如下:

            touch test.sh
            chmod a+x test.sh  
            test.sh内容如下:
            ls
            touch 1.txt 2.txt 3.txt
            ls /
            cat fork1.c

     运行shell脚本文件如下:

         peter@ubuntu:~/2308/proc/day01_code$ ./test.sh
         1.txt  3.txt   exit.c   fork2.c   main.c    myproc.c  test.sh  wait.c   waitpid.c
         2.txt  exec.c  fork1.c  getpid.c  Makefile  test.c    wait     waitpid
         bin   cdrom  etc   initrd.img      lib    lost+found  mnt  proc  run   snap  swapfile  tftpboot         u  sr  vmlinuz
         boot  dev    home  initrd.img.old  lib64  media       opt  root  sbin  srv   sys       tmp                 var    vmlinuz.old
         #include
         #include
         #include

         int main(void)
         {
             fork();
             printf("hello world\n");
             return 0;
          }

     (3)守护进程:
              该类进程在后台运行。它一般在Linux启动时开始执行,系统关闭时才结束

    二、进程API

    1.创建子进程

    pid_t fork(void);

    fork调用过程:
        1,映射新的进程虚拟空间,该进程称为子进程。
        2,将父进程的各个数据段中的数据拷贝到子进程中
        3,父子进程共享代码段
        4,fork()调用过程返回两个值:
                      第一个值:给父进程返回子进程的ID号
                      第二个值:给子进程返回0
               调用失败返回:-1
        5,父子进程,从fork()调用的下一条语句同时运行   

    实例代码如下:

    1. void fun(void)
    2. {
    3. int i;
    4. for(i = 0 ; i < 7; i++){
    5. printf("我是子进程,我要好好学习\n");
    6. sleep(1);
    7. }
    8. }
    9. int main(void)
    10. {
    11. int i;
    12. pid_t pid;
    13. if((pid = fork()) < 0){
    14. perror("fork");
    15. exit(1);
    16. }else if(!pid)
    17. fun();
    18. else
    19. for(i = 0 ; i < 7; i++){
    20. printf("我是父进程,我要努力赚钱\n");
    21. sleep(1);
    22. }
    23. return 0;
    24. }

    2.exec函数族

    //加载另一个程序在进程的空间中执行
    #include
    extern char **environ;

    int execl(const char *path, const char *arg, ... /* (char  *) NULL */);
    int execlp(const char *file, const char *arg,.../* (char  *) NULL */);
    int execle(const char *path, const char *arg,../*, (char *) NULL,char * const envp[] */);
    int execv(const char *path, char *const argv[]);
    int execvp(const char *file, char *const argv[]);
    int execve(const char *path, char *const argv[], char *const envp[]);

     函数族讲解图如下所示:

     

    实例代码如下所示: 

    1. int main(void)
    2. {
    3. int i;
    4. pid_t pid;
    5. if((pid = fork()) < 0){
    6. perror("fork");
    7. exit(1);
    8. }else if(!pid){ //子进程:执行另一个程序,如:ls
    9. #if 0
    10. //execl("/bin/ls","ls","-l",NULL);
    11. //execlp("ls","ls","-l",NULL);
    12. char * arg[] = {"ls","-l",NULL};
    13. //execv("/bin/ls",arg);
    14. execvp("ls",arg);
    15. #else
    16. //execl("/home/peter/2308/proc/day01_code/myproc","./myproc",NULL);
    17. char * env[] = {"name = peter","passwd = 123",NULL};
    18. //execle("/home/peter/2308/proc/day01_code/myproc","./myproc",NULL,env);
    19. char * arg[] = {"./myproc",NULL};
    20. execve("/home/peter/2308/proc/day01_code/myproc",arg,env);
    21. #endif
    22. }else{ //父进程循环打印
    23. for(i = 0 ; ; i++){
    24. printf("我是父进程,我要努力赚钱\n");
    25. sleep(1);
    26. }
    27. }
    28. return 0;
    29. }

    3.结束进程

    实例代码如下所示:

    1. #include <stdlib.h>
    2. void exit(int status); //在结束进程之前,会先刷新缓冲,释放缓冲区,关闭打开的文件,然后再结束进程。
    3. #include <unistd.h>
    4. void _exit(int status); //直接结束进程,不会刷新缓冲,释放缓冲区,关闭打开的文件
    5. //参数 ---status0-表示正常结束,非0-表示异常结束
    6. 例如:
    7. int main(void)
    8. {
    9. printf("hello world");
    10. //exit(1);
    11. _exit(1);
    12. while(1);
    13. return 0; //在main函数中,执行return语句,return会调用exit()
    14. }

    4.给进程收尸(释放进程占用的资源)

    (1)wait
        #include
        #include
        //作用:给任意一个子进程收尸
         如果子进程没有结束,则父进程会阻塞,直到子进程结束为止。
         如果父进程没有子进程,则wait函数立即返回。               
        pid_t wait(int *wstatus);   
        //参数  ----- 保存子进程结束状态的变量地址
        //返回值 ----成功:收尸的子进程的ID,失败:-1
        

     wait实例代码如下:

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <unistd.h>
    4. #include <sys/types.h>
    5. #include <sys/wait.h>
    6. int main(void)
    7. {
    8. int i;
    9. pid_t pid1,pid2;
    10. int status;
    11. if((pid1 = fork()) < 0){
    12. perror("fork");
    13. exit(1);
    14. }else if(!pid1){
    15. for(i = 0 ; i < 7; i++){
    16. printf("子进程1--pid = %d\n",getpid());
    17. sleep(1);
    18. }
    19. exit(0);
    20. }
    21. if((pid2 = fork()) < 0){
    22. perror("fork");
    23. exit(1);
    24. }else if(!pid2){
    25. for(i = 0 ; i < 3; i++){
    26. printf("子进程2--pid = %d\n",getpid());
    27. sleep(1);
    28. }
    29. exit(120);
    30. }
    31. if(wait(&status) < 0){
    32. perror("wait");
    33. exit(1);
    34. }
    35. printf("给子进程收完尸\n");
    36. printf("status = %d\n",WEXITSTATUS(status));
    37. return 0;
    38. }

     (2)waitpid
        //作用:给指定的进程收尸
        pid_t waitpid(pid_t pid, int *wstatus, int options);
        //参数1  ---pid:
                    pid > 0   给进程号为pid的子进程收尸
                    pid = -1  与wait()相同,给任意子进程收尸
                    pid = 0   给与当前进程在同一个进程组的中任意子进程收尸
                    pid < -1  给进程组ID为|pid|的进程组中任意子进程收尸
        //参数2 ----保存子进程结束状态的变量地址
        //参数3 ---- 选项,一般为0

    waitpid实例代码如下: 

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <unistd.h>
    4. #include <sys/types.h>
    5. #include <sys/wait.h>
    6. int main(void)
    7. {
    8. int i;
    9. pid_t pid1,pid2;
    10. int status;
    11. if((pid1 = fork()) < 0){
    12. perror("fork");
    13. exit(1);
    14. }else if(!pid1){
    15. for(i = 0 ; i < 7; i++){
    16. printf("子进程1--pid = %d\n",getpid());
    17. sleep(1);
    18. }
    19. exit(234);
    20. }
    21. if((pid2 = fork()) < 0){
    22. perror("fork");
    23. exit(1);
    24. }else if(!pid2){
    25. for(i = 0 ; i < 3; i++){
    26. printf("子进程2--pid = %d\n",getpid());
    27. sleep(1);
    28. }
    29. exit(120);
    30. }
    31. if(waitpid(pid1,&status,0) < 0){
    32. perror("wait");
    33. exit(1);
    34. }
    35. printf("给子进程收完尸\n");
    36. printf("status = %d\n",WEXITSTATUS(status));
    37. return 0;
    38. }


    总结

          本篇文章针对进程线程进行超详细讲解,希望能够帮到大家!

           以后还会给大家展现更多关于嵌入式和C语言的其他重要的基础知识,感谢大家支持懒大王!

           希望这篇博客能给各位朋友们带来帮助,最后懒大王请来过的朋友们留下你们宝贵的三连以及关注,感谢你们!

  • 相关阅读:
    Task01|GriModel统计分析(下)|方法论与一元数值检验|假设检验1
    计算机组成原理---第五章中央处理器---CPU的功能和基本结构---选择题
    1、Python 基础知识总结
    多线程之原子整数和原子引用
    常用与业务密切相关的prompt
    论文阅读 GloDyNE Global Topology Preserving Dynamic Network Embedding
    了解消息中间件的基础知识
    Java中如何优雅的处理异常
    论文阅读《LSD-SLAM: Large-Scale Direct Monocular SLAM》
    TypeScript后端http请求
  • 原文地址:https://blog.csdn.net/weixin_58070962/article/details/133323195