Linux进程实例

本文介绍了Linux中的进程,特别是fork函数的工作原理,包括其在父进程和子进程中的不同返回值。此外,还讨论了僵尸进程的产生、危害以及如何避免,以及孤儿进程的概念和处理方式。最后,提到了环境变量,包括其作用、常见类型以及如何查看和管理环境变量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • fork() 函数的使用

在这里插入图片描述

fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
1)在父进程中,fork返回新创建子进程的进程ID;
2)在子进程中,fork返回0;
3)如果出现错误,fork返回一个负值;

​ 在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。

#include <stdio.h>    
#include <unistd.h>    
    
int main() {    
  printf("before pid=%d\n", getpid());    
  pid_t pid = fork();    
  int a = 100;    
  if (pid < 0) {    
    return -1;    
  } else if (pid == 0) {    
    a = 20;    
    printf("this is child! pid=%d  a=%d\n", getpid(), a);    
  } else {    
    sleep(1);    
    printf("this is father a=%d  pid=%d\n", a, getpid());                                                                                                                   
  }    
    
  return 0;    
} 
  • 僵尸进程

    产生原因: 子进程先于父进程退出, 部分资源没回收。当进程退出并且父进程没有读取到子进程退出的返回代码是就会产生僵尸进程,僵尸进程会以终止状态保存在进程表中,并且会一直等待父进程读取退出状态代码

    #include <stdio.h>    
    #include <unistd.h>    
    #include <stdlib.h>    
        
    int main() {    
      pid_t pid;    
      pid = fork();    
      if (pid < 0) {                                            
        return -1;    
      }    
      else if (pid == 0) {    
        printf("i am child! pid=%d\n", getpid());    
        sleep(3);    
        exit(1);    
      } else {    
        printf("i am parent! pid=%d\n", getpid());    
        while(1) {    
          sleep(1);    
          printf("i don't care my child\n");    
        }    
      }    
    } 
    

在这里插入图片描述

可以看到 zombie子进程在三秒后变为僵尸状态

  • 危害

    • 维护退出状态本身就要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护。
    • 如果一个父进程创建了很多子进程,都不会回收,就会造成内存资源浪费。因为数据结构对象本身就要占内存。
    • 在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。 但是仍然为其保留一定的信息(包括进程号the process ID,退出状态the termination status of the process,运行时间the amount of CPU time taken by the process等)。直到父进程通过wait / waitpid来取时才释放。 但这样就导致了问题,如果进程不调用wait / waitpid的话,那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害,应当避免。
  • 孤儿进程

    产生原因: 父进程先于子进程退出

    一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作

    #include <stdio.h>    
    #include <unistd.h>    
    #include <stdlib.h>    
        
    int main() {    
      pid_t pid;    
      pid = fork();    
      if (pid < 0) {    
        return  -1;    
      } else if (pid == 0) {    
        printf("i am parent pid=%d\n", getpid());    
        sleep(10);    
      } else {    
        printf("i am child pid=%d\n", getpid());    
        sleep(3);    
        exit(1);    
      }    
      return 0;                                                                                                                                         
    }  
    
  • 环境变量
    在这里插入图片描述

    • 概念
      指在操作系统中用来指定操作系统运行环境的一些参数。环境变量通常具有特殊用途,在系统中具有全局特性。
      环境变量通常具有全局属性,可以被子进程继承下去。

    • 常见的环境变量
      (1)PATH:指定命令的搜索路径
      (2)HOME:指定用户的主工作目录(即用户登录到Linux系统中时,默认的目录)
      (3)HISTSIZE:指保存历史命令记录的条数
      (4)SHELL:当前Shell,它的值通常是/bin/bash

    • 查看环境变量的方法
      echo $NAME //NAME:环境变量名称

    • 和环境变量相关的命令
      (1)echo:显示某个环境变量值
      (2)export:设置一个新的环境变量
      (3)env:显示所有环境变量
      (4)unset:清楚环境变量
      (5)set:显示本地定义的shell变量和环境变量

    • setenv
      作为setenv函数
      作用:增加或者修改环境变量。
      注意:通过此函数并不能添加或修改 shell 进程的环境变量,或者说通过setenv函数设置的环境变量只在本进程,而且是本次执行中有效。如果在某一次运行程序时执行了setenv函数,进程终止后再次运行该程序,上次的设置是无效的,上次设置的环境变量是不能读到的。
      头文件:#include<stdlib.h>
      注:stdlib.h在Linux和Windows中略不同,比如setenv函数是用在linux中的,在Windows中没有setenv函数而用putenv来代替
      函数声明:int setenv(const char *name,const char * value,int overwrite);
      函数说明:setenv()用来改变或增加环境变量的内容。参数name为环境变量名称字符串。参数 value则为变量内容,参数overwrite用来决定是否要改变已存在的环境变量。如果没有此环境变量则无论overwrite为何值均添加此环境变量。若环境变量存在,当overwrite不为0时,原内容会被改为参数value所指的变量内容;当overwrite为0时,则参数value会被忽略。返回值 执行成功则返回0,有错误发生时返回-1。
      相关函数:getenv,putenv,unsetenv

      作为Linux中setenv命令
      Linux中的功能:查询或显示环境变量
      语法:setenv [变量名称] [变量值]

      setenv用于在C shell设置环境变量的值
      用法:setenv ENVVAR value
      ENVVAR 为所要设置的环境变量的名。value为所要设置的环境变量的值
      例:setenv PATH "/bin:/usr/bin:usr/sbin:"设置环境path的搜索路径为/bin,/usr/bin以及/usr/sbin

    • export
      Linux中的功能:设置或显示环境变量(比如我们要用一个命令,但这个命令的执行文件不在当前目录,这样我们每次用的时候必须制定执行文件的目录,麻烦,在代码中先执行export,这个相当于告诉程序,执行某某东西时,需要的文件或什么东西在这些目录里)
      说明:在shell中执行程序时,shell会提供一组环境变量。export可新增,修改或删除环境变量,供后续执行的程序使用。export的效力仅及于该次登陆操作。
      语法:export [-fnp] [变量名称] = [变量设置值]
      参数说明:

      -f  代表[变量名称]中为函数名称。
      -n  删除指定的变量。变量实际上并未删除,只是不会输出到后续指令的执行环境中。
      -p  列出所有的shell赋予程序的环境变量。
      延伸:export设置环境变量是暂时的,只在本次登录中有效,可修改如下文件来使命令长久有效。
      注意:
      1、执行脚本时是在一个子shell环境运行的,脚本执行完后该子shell自动退出;
      2、一个shell中的系统环境变量才会被复制到子shell中(用export定义的变量);
      3、一个shell中的系统环境变量只对该shell或者它的子shell有效,该shell结束时变量消失(并不能返回到父shell中)。
      4、不用export定义的变量只对该shell有效,对子shell也是无效的。

      一个变量创建时,它不会自动的为在它之后创建的shell进程所知。而命令export可以向后面的shell传递变量的值。当一个shell脚本调用并执行时,它不会自动得到原来脚本(调用者)里定义的变量的访问权,除非这些变量已经被显示地设置为可用。export命令可以用于传递一个或多个变量的值到任何后续脚本。

      export设置环境变量是暂时的,只在本次登录中有效,若想要使得开机时自动加载这个环境变量免除以后每次设置,可将其写入/etc/re.local

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值