进程相关的系统调用2

 

说明:只供学习交流,转载请注明出处

 

一,exec函数族

Linux系统提供了exec函数族用于对创建新进程中的数据段、代码段和堆栈段进行替换。进程调用exec函数族中的函数后,其代码段会被替换成新的代码段。同时,获得新程序的数据段和堆栈段,进程的进程号保持不变。exec函数族中的函数定义主要包括如下的几种形式:

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 *constargv[]);

int execve(const char *filename, char*const argv[], char *const envp[]);

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

可以看到这几种形式都是以exec开头。如果exec后面的字符是“l”(list的缩写),表示该种形式的exec函数可以使用可变参数(参数的个数可变);包含v字符,表示支持使用参数数组;如果是以p结尾表示如果给出的程序没有给出路径,将自动搜索系统的PATH路径。对于execlexecvexecleexecve这些不以p结束的函数,给出的要执行的可以执行的文件必须给出具体的文件所在路径。

 

注意:当进程调用一种exec函数时,该进程完全由新程序代替,而新程序则从其main()函数开始执行

 

execl函数

 

头文件

#include <unistd.h>

函数原型

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

返回值

如果执行成功则函数不会返回,执行失败者直接返回-1,失败原因存在于errno

参数说明:

path:可执行文件的全路径,包含文件名本身。

arg:执行该文件的参数列表。参数列表中第一个参数就是该可执行文件的名称,最后要以(char*0结束。

实例:

 

#include <unistd.h>

int main(void)
{
        execl("/bin/ls", "ls", "-al", "/etc/passwd", (char*)0);

        return (0);
}
运行结果:
[root@localhost test]# ./test 
-rw-r--r-- 1 root root 1508 Dec  3 05:34 /etc/passwd
[root@localhost test]#


 

相当于执行了/bin/ls –al/etc/passwd

 

 

头文件

#include <unistd.h>

函数形式

int execv(char *pathname, char *argv[]);

返回值

如果指向成功则函数不会返回,执行失败则直接返回-1,失败原因存在于errno中。

参数说明:

path:可执行文件的全路径。

arg:执行该文件的参数列表。它是一个数组指针,参数列表中第一个参数就是该可执行文件的名称,最后要以NULL结束。

实例:

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

int main(void)
{
        char *exec_argv[4];

        exec_argv[0] = "ls";
        exec_argv[1] = "-al";
        exec_argv[2] = "/etc/passwd";
        exec_argv[3] = NULL;

        execv("/bin/ls", exec_argv);

        return (0);
}
运行结果:
[root@localhost test]# ./execv
-rw-r--r-- 1 root root 1508 Dec  3 05:34 /etc/passwd
[root@localhost test]# 


 

execlp函数举例:

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

int main(int argc, char *argv[])
{
        if ( argc < 2 )
        {
                printf("Usage: %s path\n", argv[0]);
                return (1);
        }

        execlp("ls", "ls", argv[1], (char *)NULL);

        return (0);
}
运行结果:
[root@localhost test]# ./execlp /home
madplay  motion  smb  tanghui
[root@localhost test]#


 

说明:并没有给出ls命令的全部路径,函数会通过文件名从PATH环境变量中查找复合第一个参数的文件名来执行。

 

execvp函数使用范例:

 

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

int main(int argc, char *argv[])
{
        if ( argc < 2 )
        {
                printf("Usage: %s arg list...\n", argv[0]);
                exit(EXIT_FAILURE);
        }

        execvp(argv[1], &argv[1]);

        return (0);
}
运行结果:
[root@localhost test]# ./execvp ls /home/
madplay  motion  smb  tanghui
[root@localhost test]#


如果PATH环境变量中没有待执行文件的路径,我们还可以通过execleexecve这两个函数来指定环境变量。这两个函数对比其他的两组函数多了一个参数。

 

execve函数使用举例:

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

int main(void)
{
        char *argv[] = {"ls", "-al", "/etc/passwd", (char *)0};
        char *envp[] = {"PATH = /bin", 0};

        execve("/bin/ls", argv, envp);

        return (0);
}
运行结果:
[root@localhost test]# ./execve
-rw-r--r-- 1 root root 1508 Dec  3 05:34 /etc/passwd
[root@localhost test]#


execle函数这里就不举例子了,因为跟execve函数差不多,只是不用数组形式而已。

 

system函数:

#include <stdlib.h>

int system(const char *string);

功能:调用fork产生子进程,由子进程来调用/bin/sh –C string来执行参数string所代表的命令。

 

使用范例:

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

int main(void)
{
        system("ls -al /home");


        return (0);
}

运行结果:
[root@localhost test]# ./system 
total 36
drwxr-xr-x  6 root    root    4096 Feb 24 19:50 .
drwxr-xr-x 28 root    root    4096 May  4 04:50 ..
drwxr-xr-x  4 root    root    4096 Feb  4 06:07 madplay
drwxr-xr-x  2 root    root    4096 Feb 24 19:50 motion
drwx------ 20 smb     smb     4096 May  8 21:15 smb
drwx------ 17 tanghui tanghui 4096 May  4 04:51 tanghui
[root@localhost test]#


exec函数族和system函数的区别:

system是用shell来调用程序=fork+exec+waitpid,而exec是直接让你的程序是直接让你的程序代替用来的程序运行。

system是在单独的进程中执行命令,完了还会回到你的程序中。而exec函数族是直接在你的程序中执行新的代码。新的程序会覆盖你原来的程序。除非调用出错,否则你再也回不到exec后面的代码,就是说你的程序就变成了exec调用的那个程序了。看下面的例子:

例子1

execl(“/bin/ls, “ls”, “-al”, “/”, NULL;

printf(“hello linux”);

例子2

System(“ls –al /”);

printf(“hello linux”);

在例子1中,执行完exec函数后不会输出“hello linux”,因为execl里的内容代替了原程序。而例子2中会输出“hello linux”。在Linuxexec函数族一般和fork一起使用。

 

综合实例:

file_create.c:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>

void create_file(char *filename)
{
        if (creat(filename, 0666) < 0)
        {
                printf("Create file %s failure!\n", filename);
                exit(EXIT_FAILURE);
        }
        else
        {
                printf("Cteate file %s success!\n", filename);

        }
}

int main(int argc, char *argv[])
{
        if ( argc != 2 ) {
                printf("Usage: %s filename\n", argv[0]);
                exit(EXIT_FAILURE);
        }

        create_file(argv[1]);

        return (0);

}

file_exec.c:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
        if ( argc != 2 )
        {
                printf("Usage : %s filename!\n", argv[0]);
                exit(EXIT_FAILURE);
        }

        execl("./file_create", "file_create", argv[1], (char *)0);

        printf("hello linux");
        return (0);
}

运行结果:
[root@localhost test]# ls
exec  file_create  file_create.c  file_exec  file_exec.c
[root@localhost test]# ./file_exec hello
Cteate file hello success!
[root@localhost test]# 
[root@localhost test]#

 

 

 

 

 

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值