进程控制[三]

进程替换
是什么 

fork之后父子执行不同的代码,如果子进程想执行全新的代码呢?,进行程序的替换达到加载其他程序的功能,将新的程序和代码加载到磁盘重新建立映射关系。进程替换没有创建新的子进程,进程本身就存在子程序,只不过重新加载。那么如何理解将程放到内存之中呢?exec函数

为什么

#include `

int execl(const char *path, const char *arg, ...);

int execlp(const char *file, const char *arg, ...);

int execle(const char *path, const char *arg, ...,char *const envp[]);

int execv(const char *path, char *const argv[]);

int execvp(const char *file, char *const argv[]);

path是文件位置得先找到程序。....为可变参数模板,可以传入多个参数。命令行怎么执行参数怎么填。最后必须以NULL结尾。

例子

  1 #include
  2 #include
  3 #include
  4 #include
  5 
  6 int main()
  7 {
  8   printf("当前进程的开头\n");
  9   execl("/usr/bin/ls","ls","-l",NULL);                                                                                                                          
 10   printf("当前进程的结尾\n");
 11   return 0;
 12 }
~

运行结果

进程控制[三]_第1张图片

这里我们可以发现代码里写着进程的开头和结尾,但是只有进程的开头没有结尾,这是因为进程替换会将当前数据所有的代码和数据进行替换包括已经执行的和没有执行的。没有调用成功的返回值,成功了直接执行,失败了返回-1。子进程在加载新程序的时候父子进程代码必须分离,如果不替换的话子进程会影响父进程的代码。

进程控制[三]_第2张图片

进程控制[三]_第3张图片

那么我们如何执行自己写的c/c++程序呢?execl

不光c/c++写的,别的语言写的程序,如何调用呢?execlp

exec*就是加载系统底层的接口。

execve是系统最底层的接口,其他的都是封装

怎么办

一个简单的Shell程序

#include
#include
#include
#include
#include
#include
#include
//shell 父进程解析,子进程执行
#define NUM 1024
#define SIZE 32
char* argv[SIZE];
char cmd_line[NUM];
#define SEP " "
int main()
{
  while(1)
  {
    //.打出提示信息
    printf("[huanqianhan@local myshell]#");
    fflush(stdout);//刷新缓冲区 立马显示在缓冲区
    //2.获取输入字符串
     memset(cmd_line,'\0',sizeof(cmd_line));
     if(fgets(cmd_line,sizeof cmd_line,stdin)==NULL)
     {
       continue;
     }
     //printf("enho:%s\n",cmd_line);
     cmd_line[strlen(cmd_line)-1]='\0'; 
     //命令行字符串解析
     //printf("enho:%s\n",cmd_line);

     argv[0]=strtok(cmd_line,SEP);
     int index =1;
     while(argv[index++]=strtok(NULL,SEP));
     //for(index =0;argv[index];index++)
     //{
     //  printf("argv[%d]:%s\n",index,argv[index]);
     //}
     //
     //4. TODO
     //内置命令
     //让父进程,自己执行的命令叫做内置命令,内建命令,内建命令本质上就是函数的一个内置调用。内建命令本质上就是shell的函数调用
     //5.fork
     pid_t id  =fork();
     if(id==0)
     {
      printf("下面·功能让子进程执行:\n");
      // cd只会影响子进程的命令 shell当前所处的位置,一切换目录,子进程就退出了。
      // 需要判断 cd类命令不能创建子进程
      if(strcmp(argv[0],"cd")==0)
      {
        if(argv[1]!=NULL)
        {
          chdir(argv[1]);//改变 当前工作目录
          continue;
        }
      }
      execvp(argv[0],argv);
      exit(1);
     }
     else{
       int status= 0;
       pid_t ret=waitpid(id,&status,0);
       if(ret>0)
       {
         printf("子进程退出码:%d\n",WEXITSTATUS(status));
       }
     }
  }
  return 0;
}

那么最开始的环境变量哪里来的呢?卸载配置文件里面的。shell启动的时候自动读取。

你可能感兴趣的:(Linux,linux,运维,服务器)