利用fork()和execve()运行程序

#include "csapp.h"

#define MAXARGS 128

/*本案例学习fork()函数建立进程,以及execve()函数加载并运行程序*/

//eval函数用于解析命令行并执行相关命令
void eval(char *cmdline)
{
  char *argv[MAXARGS];
  char buf[MAXLINE];
  int bg;
  pid_t pid;

  strcpy(buf,cmdline); //复制字符串
  bg=parseline(buf,argv);//bg为1或0
  if(argv[0]==NULL) //参数为空,返回主函数
    return;
  if(!builtin_command(argv)) { //返回0的情况
    if((pid=fork())==0) { //新建子进程
      if(execve(argv[0],argv,environ)<0) { //运行带有参数的可执行程序,若出现错误,则execve函数会返回负数,执行错误提示,并且退出该子进程
    printf("%s:Command not found.\n",argv[0]);
    exit(0);
      }
    }
    if(!bg) { //当bg为0时,即输入命令不是空且结尾字符串不是&的情况
      int status;
      if(waitpid(pid,&status,0)<0) //若等待子进程终止或退出时发生了错误,则返回-1,并且执行以下错误提示
    printf("waitfg:waitpid error\n");
    }
    else //当bg为1时,输出进程ID及命令行参数
      printf("%d,%s",pid,cmdline);
  }
  return;
}

//builtin_command函数用于判断命令是否合法
//例如若命令行第一个字符串为quit,则表示正常退出父进程(主程序)
//若第一个字符串为&,则返回1,否则返回0
//可以认为&开头表示该行命令为注释行,不用执行
int builtin_command(char **argv)
{
  if(!strcmp(argv[0],"quit")) //quit键表示退出整个程序
    exit(0);
  if(!strcmp(argv[0],"&")) //&开头则返回1
    return 1;
  return 0; //一般情况下返回0
}

//parseline函数用于读取命令行参数,并将参数返回至argv中
int parseline(char *buf,char **argv)
{
  char *delim;
  int argc;
  int bg;

  buf[strlen(buf)-1]=‘ ‘; //将最后一位‘\0‘置为空格
  while(*buf&&(*buf==‘ ‘)) //跳过开头部分的所有空格
    buf++;

  argc=0; //用于计数(参数个数)
  while((delim=strchr(buf,‘ ‘))) { //strchr函数用于寻找字符在字符串中首次出现的位置,返回该位置指针
    argv[argc++]=buf;//将单个参数存入argv指针当中
    *delim=‘\0‘;
    buf=delim+1;//更新buf所指向的地址
    while(*buf&&(*buf==‘ ‘)) //跳过空格
      buf++;
  }

  argv[argc]=NULL;
  if(argc==0) //若参数个数为0,则返回1
    return 1;

  if((bg=(*argv[argc-1]==‘&‘))!=0) //若参数命令行最后一个字符为&,将&置为NULL,并且返回1;否则返回0
    argv[--argc]=NULL;
  return bg;

}

/*主函数入口*/
int main()
{
  char cmdline[MAXLINE];
  while(1) {
    printf("> ");
    fgets(cmdline,MAXLINE,stdin); //从终端读取输入
    if(feof(stdin))
      exit(0);
    eval(cmdline); //执行子程序
  }
}

运行示例

> ./main1.o
acbc> quit
时间: 2024-10-14 04:52:34

利用fork()和execve()运行程序的相关文章

如何利用 JConsole观察分析Java程序的运行,进行排错调优(转)

如何利用 JConsole观察分析Java程序的运行,进行排错调优 博客分类: JAVA JavaOracleSUNEclipseJDK 一.JConsole是什么 从Java 5开始 引入了 JConsole.JConsole 是一个内置 Java 性能分析器,可以从命令行或在 GUI shell 中运行.您可以轻松地使用 JConsole(或者,它更高端的 “近亲” VisualVM )来监控 Java 应用程序性能和跟踪 Java 中的代码. 二.如何启动JConsole 如果是从命令行启

.net利用程序集的GUID解决程序只能运行一次的问题

可以解决同名的程序集(但非同一程序集)只能运行一次的问题,网上很资料都是只检测程序是否同名,不能真正的保证是同一程序集. private bool prevInstance() { Process[] myProcesses= Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName); if (myProcesses.Length > 1) { GuidAttribute curGuid = (GuidAttribut

fork与 execve的区别

在父进程中fork一个子进程,在子进程中调用exec函数启动新的程序.exec函数一共有六个,其中execve为内核级系统调用,其他(execl,execle,execlp,execv,execvp)都是调用execve的库函数. #include<unistd.h> 函数定义 int execve(const char *filename, char *const argv[ ], char *const envp[ ]); 返回值 函数执行成功时没有返回值,执行失败时的返回值为-1. 函数

单线程排序和利用Fork/Join进行多线程并行排序的简单对比

Fork/Join框架自从在JDK7中引进之后,对并行计算的设计带来了更多便利. 本文使用java原生的排序方法Array.sort单线程排序,和利用Fork/Join框架进行任务分割设计的快速排序进行对比. 首先,使用以下方法构造一个简单的文件样本,目标是生成一个文本文件,10000000行,每行为一个20000以内的随机数: package sort; import java.io.File; import java.io.FileWriter; import java.io.IOExcep

利用fork实现并发服务器

(1) fork 浅析 linux 中, 一个进程可以通过fork()系统调用来创建一个与自己相同的子进程, 这个子进程是父进程的克隆, 他继承了父进程的整个地址空间, 包括进程上下文, 堆栈地址, 内存信息, 进程控制块等.值得注意的是, 调用fork一次, 他却返回两次, 一次是在父进程中返回子进程的进程id, 一次是在子进程中返回0, 这看起来有点难理解, 我们先看下面这段程序: #include <unistd.h> #include <stdio.h> #include

实现关闭ssh继续运行程序---tmux

问题1:为什么ssh一关闭,程序就不再运行了 元凶:SIGHUP 信号 让我们来看看为什么关掉窗口/断开连接会使得正在运行的程序死掉. 在Linux/Unix中,有这样几个概念: 进程组(process group):一个或多个进程的集合,每一个进程组有唯一一个进程组ID,即进程组长进程的ID. 会话期(session):一个或多个进程组的集合,有唯一一个会话期首进程(session leader).会话期ID为首进程的ID. 会话期可以有一个单独的控制终端(controlling termin

操作系统篇-hello world(免系统运行程序)

  一.前言 今天起开始分享关于操作系统的相关知识,本人也是菜鸟一个,正处于学习阶段,这整个操作系统篇也是我边学习边总结的一些结果,希望能给正在学习或者有意向学习操作系统的童鞋带来帮助. 二.有关知识 在进入代码之前,先给大家普及一些硬件知识,如果你已经具备了这方面的知识,可以直接略过这部份. 1.计算机怎么启动操作系统的? 首先,我们思考一个问题,为什么一个硬盘安装系统之后打开计算机电源之后就能正常加载启动呢?这看起来似乎很智能,似乎计算机像活的一样会自动去硬盘中找系统代码并自行加载.其实不然

gdb系列之四 在GDB里运行程序

在你开始在GDB里运行程序前,你需要在编译的时候产生调试信息. 你可以在你选定的环境里带参数(如果有的话)的启动GDB.如果你是在本地调试,你可以重定向输入输出,调试一个已运行 的进程,或者结束一个进程. 4.1 为调试而编译 为了有效的调试程序,你需要在编译的时候产生调试信息.调试信息存储在目标文件里:调试信息描述了数据和函数的类型, 源代码和可执行代码的对应关系. 编译时指定编译器的'-g'选项可以产生调试信息. 在编译给你的客户发布的程序时,可以用'-O'选项指定编译器进行优化.然而,许多

利用C语言编辑画图程序的实现方法

不知道大家在进行开发县级电网调度自动化系统的时候,是否都会遇到一个问题就是:要绘制一个电力系统一次接线图.大家都应该知道其实电力系统的一次接线图是较为复杂的,如果想要使用一般的编程方法来进行绘制的话,基本上就是行不通的.那么我们应该怎样才可以更加的高效直接呢?今天小编就会给大家介绍一个方法,那就是:利用C语言编辑画图程序的实现方法.希望这篇教程对于大家有所帮助. 一.实现方法 在教程开始之前,小编先为大家介绍一下在编程程序里面早已定义了几个特殊按钮.为什么小编要为大家介绍这几个特殊按钮呢?那是因