• linux进程


    目录

    一,进程相关概念

    二,进程的特征

    三,进程的状态

    四,进程种类

    1,交互进程:

    2,批处理进程:

    3,守护进程:

    五,进程系统调用

    1,创建进程

    2,exec函数族 -----//在进程中加载另一个程序执行 

    3、结束进程

    4、获取进程的pid  

    5、进程收尸


    一,进程相关概念

        
        程序是语句的集合
        进程是程序的一次执行过程。
        每一个进程都有一个唯一的ID,可以通过getpid()获取
        
        例如: 
        #include
        #include

        int main(void)
        {
            while(1){
                printf("%d\n",getpid());
                sleep(1);
            }   
            return 0;
        }

        进程和程序的区别
        程序是静态的,它是一些保存在磁盘上的指令的有序集合,没有任何执行的概念
        
        进程是一个动态的概念,它是程序执行的过程,包括创建、调度和消亡

        
        进程是系统分配资源的最小单位  
        线程是cpu调度的最小单位

    二,进程的特征

        动态性  -----是程序的执行过程
        并发性  -----多个进程可以同时运行
        独立性  -----系统给每一个进程会分配独立的虚拟空间
        异步性  ----- 进程之间各自运行,不会干扰
        

    三,进程的状态

        参考:3_进程的状态.tif
        

    四,进程种类

    1,交互进程:

    该类进程是由shell控制和运行的。交互进程既可以在前台运行,也可以在后台运行。

    2,批处理进程:

    该类进程不属于某个终端,它被提交到一个队列中以便顺序执行。
             例如: shell脚本程序 
             hello.sh
                ls -l 
                pwd
                touch abc.txt

    3,守护进程:

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

    五,进程系统调用

    1,创建进程

            #include
            #include
            pid_t vfork(void);//--子进程结束父进程再开始
            pid_t fork(void);
            //返回值--失败:-1,成功:给父进程返回子进程的ID,给子进程返回0        当调用fork()函数时,计算机会执行以下几步:
            1》映射一个进程虚拟的内存空间,原来的进程称为父进程,新的虚拟空间中运行的进程称为子进程
            2》将父进程所有数据段中的数据拷贝到子进程对应的段中
            3》父子进程共享代码段
            4》给父进程返回子进程的ID,给子进程返回0
            5》父子进程从fork()函数调用的下一条语句同时开始运行。
            
            例如: 

    1.         #include
    2.         #include
    3.         #include
    4.         #include
    5.         int main(void)
    6.         {
    7.             pid_t pid;
    8.             pid = fork();
    9.             if(pid < 0){ 
    10.                 perror("fork");
    11.                 exit(1);
    12.             }if(pid > 0){ 
    13.                 //父进程执行
    14.                 printf("我是老子,我的ID:%d\n",getpid());
    15.                 while(1){
    16.                     printf("没事生孩子!\n");
    17.                     sleep(1);
    18.                 }   
    19.             }else{
    20.                 //子进程执行
    21.                 printf("我是儿子,我的ID:%d\n",getpid());
    22.                 while(1){
    23.                     printf("找个女朋友!\n");
    24.                     sleep(1);
    25.                 }   
    26.             }   
    27.             printf("hello world\n");
    28.             return 0;
    29.         }

    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[]);
           
           //添加环境变量---export PATH=$PATH:环境变量路径    
            例如: 

    1.         #include <stdio.h>
    2.         #include <stdlib.h>
    3.         #include <unistd.h>
    4.         int main(void)
    5.         {
    6.             pid_t pid;
    7.             if((pid = fork()) < 0){
    8.                 perror("fork");
    9.                 exit(1);
    10.             }else if(pid > 0){
    11.                 while(1){
    12.                     printf("this is parent process!\n");
    13.                     sleep(1);
    14.                 }
    15.             }else{
    16.         #if 0
    17.             execl("/bin/ls","ls","-l",NULL);
    18.             execlp("ls","ls","-l",NULL);
    19.             char * env[] = {"name=jack","passwd=123",NULL};
    20.             execle("./envtest","./envtest",NULL,env);
    21.             char *arg[] = {"ls","-l",NULL};
    22.             //execv("/bin/ls",arg);
    23.             //execvp("ls",arg);
    24.         #else
    25.             char *arg[] = {"./envtest",NULL};
    26.             char * env[] = {"name=jack","passwd=123",NULL};
    27.             execve("./envtest",arg,env);
    28.         #endif
    29.             //执行exec函数族后,后面的代码全部被加载的另一个程序替换,所以无法执行的
    30.             }
    31.             return 0;
    32.         }
    33.         
    34.         //加载自己写的打印环境变量的程序,代码如下:
    35.         #include <stdio.h>
    36.         
    37.         extern char **environ;
    38.         int main(void)
    39.         {
    40.             int i;
    41.             for(i = 0; environ[i]!= NULL; i++)
    42.                 printf("%s\n",environ[i]);
    43.             return 0;
    44.         }


        

    3、结束进程

             #include
             void _exit(int status);  //直接结束进程
           例如: 

    1.         int main(void)
    2.         {
    3.             printf("hello world");
    4.             _exit(0);        //结束程序,不刷新缓冲区,所以hello world不能显示在屏幕上
    5.             return 0;
    6.         }
    7.        
    8.         #include <stdlib.h>
    9.         void exit(int status);   //结束进程之前,会先刷新缓冲区,并释放资源
    10.         例如: 
    11.         int main(void)
    12.         {
    13.             printf("hello world");
    14.             exit(0);        //结束进程之前,会先刷新缓冲区,并释放资源,所以hello world可以显示在屏幕上
    15.             return 0;    //在main()函数中,执行return时,会自动调用exit();
    16.         }


            

    4、获取进程的pid  

               #include
               #include            pid_t getpid(void);    //获取当前进程的pid
               pid_t getppid(void);   //获取当前进程的父进程pid
            例如: 

    1.             #include
    2.             #include
    3.             #include
    4.             int main(void)
    5.             {
    6.                 printf("父进程ID = %d\n",getppid());
    7.                 printf("进程ID = %d\n",getpid());
    8.                 return 0;
    9.             }

    5、进程收尸

           #include
           #include        // 给任意一个子进程收尸,哪个先结束就给哪个收尸
           pid_t wait(int *wstatus);  
           //参数  ------ 获取子进程结束的状态
           //返回值 ---成功:收尸的子进程pid,失败:-1
           
           //当调用wait()给子进程收尸时:
           1)如果父进程没有子进程,则wait()立即返回
           2)如果子进程尚未结束,则wait()使父进程阻塞,直到有一个子进程结束时返回。
           3)如果子进程已经结束,则wait()立即返回
           例如: 

    1.         #include
    2.         #include
    3.         #include
    4.         #include
    5.         #include
    6.         int main(void)
    7.         {
    8.             pid_t pid;
    9.             if((pid = fork()) < 0){
    10.                 perror("fork");
    11.                 exit(1);
    12.             }else if(pid > 0){
    13.                 int wstatus;
    14.                 //wait(NULL);
    15.                 wait(&wstatus);
    16.                 printf("%d\n",WEXITSTATUS(wstatus));
    17.                 printf("helo world\n");
    18.                 printf("父进程:pid = %d\n",getpid());
    19.                 printf("父进程:ppid = %d\n",getppid());
    20.             }else{
    21.                 printf("hello world\n");
    22.                 printf("子进程:pid = %d\n",getpid());
    23.                 printf("子进程:ppid = %d\n",getppid());
    24.                 exit(89);
    25.             }
    26.             return 0;
    27.         }

           
           
           //给指定的子进程收尸
           pid_t waitpid(pid_t pid, int *wstatus, int options);
           //参数1 ---- 指定的子进程pid: 
                            pid > 0,给指定的子进程收尸 
                            pid=-1:等待任何一个子进程退出,此时和wait作用一样。
                            pid=0:等待其组ID等于调用进程的组ID的任一子进程。
                            pid<-1:等待其组ID等于pid的绝对值的任一子进程。
          //参数2 ---- 子进程结束状态
          //参数3 ----- wait的选项,一般为0
          //返回值 -----成功:收尸的子进程pid,失败:-1
        
          例如: 

    1.        int main(void)
    2.         {
    3.             pid_t pid1,pid2;
    4.             int i;
    5.             //创建子进程1
    6.             if((pid1 = fork()) < 0){
    7.                 perror("fork");
    8.                 exit(1);
    9.             }else if(!pid1){
    10.                 //子进程1
    11.                 for(i = 0; i < 5; i++){
    12.                     printf("我是子进程1\n");
    13.                     sleep(1);
    14.                 }
    15.                 exit(0);
    16.             }
    17.             //创建子进程2
    18.             if((pid2 = fork()) < 0){
    19.                 perror("fork");
    20.                 exit(1);
    21.             }else if(!pid2){
    22.                 //子进程2
    23.                 for(i = 0; i < 9; i++){
    24.                     printf("我是子进程2\n");
    25.                     sleep(1);
    26.                 }
    27.                 exit(0);
    28.             }
    29.             //父进程
    30.             waitpid(pid1,NULL,0);
    31.             printf("我是父进程!\n");
    32.             return 0;
    33.         }


     

  • 相关阅读:
    国产开发板——香橙派Kunpeng Pro的上手初体验
    【文本检测与识别白皮书-3.2】第二节:基于注意力机制和CTC的场景文本识别方法的对比
    软件测试需求分析是什么?为什么需要进行测试需求分析?
    CVPR2022 | 长期行动预期的Future Transformer
    Flutter笔记:拖拽手势
    一种视频防抖的车辆检测算法
    【无标题】
    直流无刷电机(BLDC)转速闭环调速系统及Matlab/Simulink仿真分析
    (21)STM32——通过键盘控制舵机和LED灯(利用正点原子USMART实现)
    Mybatis-plus的介绍与使用
  • 原文地址:https://blog.csdn.net/qq_54075859/article/details/126612007