linux进程概念及相关操作--创建进程、exec函数族、结束进程、获取进程的pid 、进程收尸

目录

一,进程相关概念

二,进程的特征

三,进程的状态

四,进程种类

1,交互进程:

2,批处理进程:

3,守护进程:

五,进程系统调用

1,创建进程

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

3、结束进程

4、获取进程的pid  

5、进程收尸


一,进程相关概念

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

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

        #include <stdio.h>
        #include <stdlib.h>
        #include <sys/types.h>
        #include <unistd.h>

        int main(void)
        {
            pid_t pid;

            pid = fork();
            if(pid < 0){ 
                perror("fork");
                exit(1);
            }if(pid > 0){ 
                //父进程执行
                printf("我是老子,我的ID:%d\n",getpid());
                while(1){
                    printf("没事生孩子!\n");
                    sleep(1);
                }   
            }else{
                //子进程执行
                printf("我是儿子,我的ID:%d\n",getpid());
                while(1){
                    printf("找个女朋友!\n");
                    sleep(1);
                }   
            }   
            printf("hello world\n");
            return 0;
        }

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

        #include <unistd.h>

       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:环境变量路径    
        例如: 

        #include <stdio.h>
        #include <stdlib.h>
        #include <unistd.h>

        int main(void)
        {
            pid_t pid;

            if((pid = fork()) < 0){
                perror("fork");
                exit(1);
            }else if(pid > 0){
                while(1){
                    printf("this is parent process!\n");
                    sleep(1);
                }

            }else{
        #if 0
            execl("/bin/ls","ls","-l",NULL);
            execlp("ls","ls","-l",NULL);
            char * env[] = {"name=jack","passwd=123",NULL};
            execle("./envtest","./envtest",NULL,env);
            char *arg[] = {"ls","-l",NULL};
            //execv("/bin/ls",arg);
            //execvp("ls",arg);
        #else
            char *arg[] = {"./envtest",NULL};
            char * env[] = {"name=jack","passwd=123",NULL};
            execve("./envtest",arg,env);
        #endif
            //执行exec函数族后,后面的代码全部被加载的另一个程序替换,所以无法执行的
            }
            return 0;
        }
        
        //加载自己写的打印环境变量的程序,代码如下:
        #include <stdio.h>
        
        extern char **environ;
        int main(void)
        {
            int i;

            for(i = 0; environ[i]!= NULL; i++)
                printf("%s\n",environ[i]);
            return 0;
        }


    

3、结束进程

         #include <unistd.h>
         void _exit(int status);  //直接结束进程
       例如: 

        int main(void)
        {
            printf("hello world");
            _exit(0);        //结束程序,不刷新缓冲区,所以hello world不能显示在屏幕上
            return 0;
        }

       
        #include <stdlib.h>
        void exit(int status);   //结束进程之前,会先刷新缓冲区,并释放资源
        例如: 
        int main(void)
        {
            printf("hello world");
            exit(0);        //结束进程之前,会先刷新缓冲区,并释放资源,所以hello world可以显示在屏幕上
            return 0;    //在main()函数中,执行return时,会自动调用exit();
        }


        

4、获取进程的pid  

           #include <sys/types.h>
           #include <unistd.h>           pid_t getpid(void);    //获取当前进程的pid
           pid_t getppid(void);   //获取当前进程的父进程pid
        例如: 

            #include <stdio.h>
            #include <sys/types.h>
            #include <unistd.h>

            int main(void)
            {
                printf("父进程ID = %d\n",getppid());
                printf("进程ID = %d\n",getpid());
                return 0;
            }

5、进程收尸

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

        #include <stdio.h>
        #include <stdlib.h>
        #include <sys/types.h>
        #include <unistd.h>
        #include <sys/wait.h>

        int main(void)
        {
            pid_t pid;

            if((pid = fork()) < 0){
                perror("fork");
                exit(1);
            }else if(pid > 0){
                int wstatus;
                //wait(NULL);
                wait(&wstatus);
                printf("%d\n",WEXITSTATUS(wstatus));
                printf("helo world\n");
                printf("父进程:pid = %d\n",getpid());
                printf("父进程:ppid = %d\n",getppid());
            }else{
                printf("hello world\n");
                printf("子进程:pid = %d\n",getpid());
                printf("子进程:ppid = %d\n",getppid());
                exit(89);
            }
            return 0;
        }

       
       
       //给指定的子进程收尸
       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
    
      例如: 

       int main(void)
        {
            pid_t pid1,pid2;
            int i;

            //创建子进程1
            if((pid1 = fork()) < 0){
                perror("fork");
                exit(1);
            }else if(!pid1){
                //子进程1
                for(i = 0; i < 5; i++){
                    printf("我是子进程1\n");
                    sleep(1);
                }
                exit(0);
            }
            //创建子进程2
            if((pid2 = fork()) < 0){
                perror("fork");
                exit(1);
            }else if(!pid2){
                //子进程2
                for(i = 0; i < 9; i++){
                    printf("我是子进程2\n");
                    sleep(1);
                }
                exit(0);
            }
            //父进程
            waitpid(pid1,NULL,0);
            printf("我是父进程!\n");

            return 0;
        }


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值