系统调用execve()

execve()系统调用学习

先来一个小程序,  它的功能是打印父子进程号, 传入的全部参数及两个环境变量(如果有):

process.c

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

int main(int argc,char *argv[],char *env[])
{
    int i;   char *p;

    printf("\n=========I am a process image!============\n");
    printf("\nMy pid = %d,  parentpid = %d\n", getpid(), getppid());

    for(i=0; i< argc; i++)
        printf("\nargv[%d]:  %s\n",i ,argv[i]);

    p = getenv("env1");
    if(p != NULL)
        printf("\nenv1 = %s\n",p);

    p = getenv("env2");
    if(p != NULL)
        printf("\nenv2 = %s\n\n",p);

    printf("\n============= process =================\n\n");

    sleep(atoi(argv[1]));

    return 99;
}

另一段代码myexec.c如下:

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

#define ERROR(flag)                     if(flag)                {                        printf("%d: ",__LINE__);        fflush(stdout);                perror("error");            exit(errno);            }

int main()
{
    int ret = 0;

    char *argv[] = {"11","22",NULL};
    char *env[] = {"env1=1111111111111","env2=2222222222222",NULL};

    printf("\nthis is myexec file, pid is %d,  ppid is %d\n",getpid(),getppid());

//    ret = execl("process","11","22",NULL);
//    ret = execlp("process","11","22",NULL);
//    ret = execle("process","11","22",NULL,NULL);
//    ret = execv("process",argv);
//    ret = execvp("process",argv);
    ret = execve("process",argv,env);
    ERROR(ret == -1);

    return 0;
}

执行"make process myexec"后, 在当前目录下生成process和myexec两个可执行文件. 执行结果如下:

porcess.c代码将myexec.c代码执行时execve()系统调用传入的参数及环境变量息数打印了出来.

-------------------------------------------------------------------------------------------------------------------------------------------------

将myexec.c改造成如下代码:

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

#define ERROR(flag)                     if(flag)                {                        printf("%d: ",__LINE__);        fflush(stdout);                perror("error");            exit(errno);            }

int main(int argc,char *argv[],char *env[])
{
    pid_t pid;

    pid = fork();
    //pid = vfork();
    ERROR(pid == -1);
    if(pid == 0)
    {
        printf("\nChild process is running\n");
        printf("\nMy pid = %d ,parent pid = %d\n",getpid(),getppid());

        char *arglist[] = {"sleep","3",NULL};
        execvp("./process",arglist);
        printf("process never go to here!\n");

        _exit(0);
    }

    int stat;
    pid_t child_pid;

    child_pid = wait(&stat);
    printf("child process has exited, pid = %d\n\n",child_pid);

    if(WIFEXITED(stat))
        printf("child exited with code %d\n\n",WEXITSTATUS(stat));
    else
        printf("child exit abnormally\n\n");

    return 0;
}

执行"make myexec process" 后, 执行结果如下图:

子进程通过execvp()执行process. 父进程通过wait()取得子进程号及其(正常)退出运行时(通过WEXITSTAYUS()取得)的返回值.

--------------------------------------------------------------------------------------------------------------------------------------------------------------

一种通过c代码运行终端命令的方法:

mysystem,c

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

int main(int argc, char *argv[])
{
    system("ls --color=tty");
    return 0;
}

编译链接后运行, 其执行效果与在终端运行"ls --color=tty"命令的效果相同.

时间: 2024-10-12 11:40:16

系统调用execve()的相关文章

Linux内核源代码情景分析-execve()

子进程开始执行execve: execve("/bin/echo", args, NULL}); 系统调用execve内核入口是sys_execve,代码如下: asmlinkage int sys_execve(struct pt_regs regs) { int error; char * filename; filename = getname((char *) regs.ebx);//ebx为"/bin/echo",把字符串从用户空间拷贝到系统空间 erro

Linux开机启动十步骤

开机过程指的是从打开计算机电源直到LINUX显示用户登录画面的全过程.分析LINUX开机过程也是深入了解LINUX核心工作原理的一个很好的途径. 启动第一步--加载BIOS 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息.设备启动顺序信息.硬盘信息.内存信息.时钟信息.PnP特性等等.在此之后,计算机心里就有谱了,知道应该去读取哪个硬件设备了.在BIOS将系统的控制权交给硬盘第一个扇区之后,就

Linux内核分析——第七周学习笔记20135308

第七周 可执行程序的装载 一.预处理.编译.链接和目标文件的格式 1.可执行程序是怎么来的 C代码—>预处理—>汇编代码—>目标代码—>可执行文件 .asm汇编代码 .o目标码 a.out可执行文件 预处理负责把include的文件包含进来及宏替换工作. 2.目标文件的格式ELF (1)常见的ELF格式文件: (2)ABI——应用程序二进制接口 在目标文件中,他已经是二进制兼容,即适应二进制指令. (3)ELF中三种目标文件: 一个可重定位(relocatable)文件保存着代码和

LINUX内核分析第七周学习总结——可执行程序的装载

LINUX内核分析第六周学习总结——进程的描述和进程的创建 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.知识概要 (一)预处理.编译.链接和目标文件的格式 1.可执行程序是怎么得来的 2.目标文件的格式ELF 3.静态链接的ELF可执行文件和进程的地址空间 (二)可执行程序.共享库和动态加载 1.装载可执行程序之前的工作 2.装载时动态链接和运行时动态链接应用举例 (三)

Linux下Fork与Exec使用

http://www.cnblogs.com/hicjiajia/archive/2011/01/20/1940154.html Linux下Fork与Exec使用 一.引言 对于没有接触过Unix/Linux操作系统的人来说,fork是最难理解的概念之一:它执行一次却返回两个值.fork函数是Unix系统最杰出的成就之一,它是七十年代UNIX早期的开发者经过长期在理论和实践上的艰苦探索后取得的成果,一方面,它使操作系统在进程管理上付出了最小的代价,另一方面,又为程序员提供了一个简洁明了的多进程

Linux系统开机启动时的工作原理

Linux系统开机启动时的工作原理也是深入了解Linux系统核心工作原理的一个很好的途径. 启动第一步--加载BIOS 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息.设备启动顺序信息.硬盘信息.内存信息.时钟信息.PnP特性等等.在此之后,计算机心里就有谱了,知道应该去读取哪个硬件设备了.在BIOS将系统的控制权交给硬盘第一个扇区之后,就开始由Linux来控制系统了. 启动第二步--读取MB

Linux系统开机启动流程介绍

一.linux系统进程启动流程图: 二.简单概括描述linux系统从开机到登陆界面的启动过程 1.开机BIOS自检 2.MBR引导 3.grub引导菜单 4.加载内核 5.启动init进程 6.读取inittab文件执行rc.sysinit.rc等脚本 7.启动mingetty进入系统登录界面 三.详细剖析linux系统启动过程 1.POST开机自检 电脑主机打开电源的时候随后会听到滴的一声响系统启动开始了开机自检POST-power on self Test自检开始这个过程中主要是检测计算机硬

20135327郭皓--Linux内核分析第七周 可执行程序的装载

第七周 可执行程序的装载 郭皓 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 一.预处理,编译,链接和目标文件格式 1.可执行程序是怎么得来的 c代码->预处理->汇编代码->汇编器->目标代码->链接成可执行文件->加载到内核执行 2.目标文件的格式ELF 符号修饰标准.变量内层布局.函数调用方式等这些跟可执行代码二进制兼容性相关的内容称为ABI

20135201李辰希 《Linux内核分析》第七周 可执行程序的装载

李辰希  原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.预处理.编译.链接和目标文件的格式 1.可执行程序是怎么得来的 编译链接的过程 1.预处理阶段 gcc -E -o XX.cpp XX.c -m32 XX.cpp是预处理文件 2.编译器生成汇编代码阶段 gcc -x cpp-output -S -o hello.s hello.cpp -m32 XX.s是汇编代码 3.汇编器