exec 函数族

转自:http://www.cnblogs.com/mickole/p/3187409.html

linux系统编程之进程(五):exec系列函数(execl,execlp,execle,execv,execvp)使用

本节目标:

  • exec替换进程映像
  • exec关联函数组(execl、execlp、execle、execv、execvp)

一,exec替换进程映像

在进程的创建上Unix采用了一个独特的方法,它将进程创建与加载一个新进程映象分离。这样的好处是有更多的余地对两种操作进行管理。

当我们创建了一个进程之后,通常将子进程替换成新的进程映象,这可以用exec系列的函数来进行。当然,exec系列的函数也可以将当前进程替换掉。

例如:在shell命令行执行ps命令,实际上是shell进程调用fork复制一个新的子进程,在利用exec系统调用将新产生的子进程完全替换成ps进程。

二,exec系列函数(execl、execlp、execle、execv、execvp)

包含头文件<unistd.h>

功能:

    用exec函数可以把当前进程替换为一个新进程,且新进程与原进程有相同的PID。exec名下是由多个关联函数组成的一个完整系列,

头文件<unistd.h>

extern char **environ; 

原型:

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参数表示你要启动程序的名称包括路径名

arg参数表示启动程序所带的参数,一般第一个参数为要执行命令名,不是带路径且arg必须以NULL结束

返回值:成功返回0,失败返回-1

注:上述exec系列函数底层都是通过execve系统调用实现:

       #include <unistd.h>

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

DESCRIPTION: 
       execve() executes the program pointed to by filename.  filename must be 
       either a binary executable, or a script starting with  a  line  of  the form 

以上exec系列函数区别:

1,带l 的exec函数:execl,execlp,execle,表示后边的参数以可变参数的形式给出且都以一个空指针结束。

示例:

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{printf("entering main process---\n");execl("/bin/ls","ls","-l",NULL);printf("exiting main process ----\n");return 0;
}
复制代码

QQ截图20130712225614

利用execl将当前进程main替换掉,所有最后那条打印语句不会输出

2,带 p 的exec函数:execlp,execvp,表示第一个参数path不用输入完整路径,只有给出命令名即可,它会在环境变量PATH当中查找命令

示例:

当不带p但没给出完整路径时:

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{printf("entering main process---\n");execl("/bin/ls","ls","-l",NULL);printf("exiting main process ----\n");return 0;
}
复制代码

结果:

QQ截图20130712230253

结果显示找不到,所有替换不成功,main进程继续执行

现在带p:

QQ截图20130712230432

替换成功

3,不带 l 的exec函数:execv,execvp表示命令所需的参数以char *arg[]形式给出且arg最后一个元素必须

是NULL

示例:

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{printf("entering main process---\n");int ret;char *argv[] = {"ls","-l",NULL};ret = execvp("ls",argv);if(ret == -1)perror("execl error");printf("exiting main process ----\n");return 0;
}
复制代码

结果:

QQ截图20130712230956

进程替换成功

4,带 e 的exec函数:execle表示,将环境变量传递给需要替换的进程

从上述的函数原型中我们发现:

extern char **environ;

此处的environ是一个指针数组,它当中的每一个指针指向的char为“XXX=XXX”

environ保存环境信息的数据可以env命令查看:

QQ截图20130712231740

它由shell进程传递给当前进程,再由当前进程传递给替换的新进程

示例:execle.c

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, char *argv[])
{//char * const envp[] = {"AA=11", "BB=22", NULL};printf("Entering main ...\n");int ret;ret =execl("./hello", "hello", NULL);//execle("./hello", "hello", NULL, envp);if(ret == -1)perror("execl error");printf("Exiting main ...\n");return 0;
}
复制代码

hello.c

复制代码
#include <unistd.h>
#include <stdio.h>
extern char** environ;int main(void)
{printf("hello pid=%d\n", getpid());int i;for (i=0; environ[i]!=NULL; ++i){printf("%s\n", environ[i]);}return 0;
}
复制代码

结果:

QQ截图20130712232918

可知原进程确实将环境变量信息传递给了新进程

那么现在我们可以利用execle函数自己给的需要传递的环境变量信息:

示例程序:execle.c

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, char *argv[])
{char * const envp[] = {"AA=11", "BB=22", NULL};printf("Entering main ...\n");int ret;//ret =execl("./hello", "hello", NULL);ret =execle("./hello", "hello", NULL, envp);if(ret == -1)perror("execl error");printf("Exiting main ...\n");return 0;
}
复制代码

hello.c

复制代码
#include <unistd.h>
#include <stdio.h>
extern char** environ;int main(void)
{printf("hello pid=%d\n", getpid());int i;for (i=0; environ[i]!=NULL; ++i){printf("%s\n", environ[i]);}return 0;
}
复制代码

结果:

QQ截图20130712233335

确实将给定的环境变量传递过来了

 

三,fcntl()函数中的FD_CLOEXEC标识在exec系列函数中的作用

#include <unistd.h> 
#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );

File descriptor flags 
      The following commands manipulate the  flags  associated  with  a  file 
      descriptor.   Currently, only one such flag is defined: FD_CLOEXEC, the 
      close-on-exec flag.  If the FD_CLOEXEC bit is 0,  the  file  descriptor 
      will remain open across an execve(2), otherwise it will be closed.

     //如果FD_CLOEXEC标识位为0,则通过execve调用后fd依然是打开的,否则为关闭的

      F_GETFD (void) 
             Read the file descriptor flags; arg is ignored.

      F_SETFD (long) 
             Set the file descriptor flags to the value specified by arg.

如:fcntl(fd, F_SETFD, FD_CLOEXEC);

测试示例:

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{printf("Entering main ...\n");int ret = fcntl(1, F_SETFD, FD_CLOEXEC);if (ret == -1)perror("fcntl error");int val;val =execlp("ls", "ls","-l", NULL);if(val == -1)perror("execl error");printf("Exiting main ...\n");return 0;
}
复制代码

结果:

QQ截图20130712235308

1关闭(标准输出关闭)ls -l无法将结果显示在标准输出


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384412.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统编程(四)信号

Linux系统编程&#xff08;四&#xff09;信号一、什么是信号&#xff1f;1、信号的本质2、信号来源硬件来源软件来源二、常见信号1.可靠信号和不可靠信号2、不可靠信号主要有以下问题:3、可靠信号与不可靠信号注册机制三、信号处理方式四、信号处理过程五、未决信号和阻塞信号…

SIGCHLD信号回收子进程

SIGCHLD信号回收子进程代码问题注意点代码 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #include <signal.h>void handler(int signo) {int status; pid_t pid;while ((pid waitpid(0, &status…

Wait waitpid

转自&#xff1a;http://www.cnblogs.com/mickole/p/3187770.html linux系统编程之进程&#xff08;六&#xff09;&#xff1a;父进程查询子进程的退出,wait,waitpid 本节目标&#xff1a; 僵进程SIGCHLDwaitwaitpid 一&#xff0c;僵尸进程 当一个子进程先于父进程结束运行时…

Linux C++ 简单爬虫

转载&#xff1a;http://blog.csdn.net/orthocenterchocolate/article/details/38665937 方便易用&#xff0c;传入URL&#xff0c;返回对应页面的内容 [cpp] view plaincopy #include <iostream> #include <string> #include <netdb.h> #include <…

Linux系统编程(七)消息队列

Linux系统编程&#xff08;七&#xff09;消息队列一、什么是消息队列二、消息队列内部原理三、实现消息队列的收发1.发送消息队列2.接收消息队列四、消息队列与命名管道的比较一、什么是消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。每个数据块都…

基于Linux的SOCKET编程之TCP半双工Client-Server聊天程序

转自&#xff1a;http://blog.csdn.net/apollon_krj/article/details/53398448#0-tsina-1-64987-397232819ff9a47a7b7e80a40613cfe1 所谓半双工通信&#xff0c;即通信双方都可以实现接发数据&#xff0c;但是有一个限制&#xff1a;只能一方发一方收&#xff0c;之后交换收发对…

智能算法(GA、DBO等)求解阻塞流水车间调度问题(BFSP)

先做一个声明&#xff1a;文章是由我的个人公众号中的推送直接复制粘贴而来&#xff0c;因此对智能优化算法感兴趣的朋友&#xff0c;可关注我的个人公众号&#xff1a;启发式算法讨论。我会不定期在公众号里分享不同的智能优化算法&#xff0c;经典的&#xff0c;或者是近几年…

Linux socket编程,对套接字进行封装

转自&#xff1a;http://www.cnblogs.com/-Lei/archive/2012/09/04/2670942.html 下面是对socket操作的封装&#xff0c;因为在Linux下写中文到了windows里面会乱码&#xff0c;所以注释用英文来写&#xff0c;有空再查下解决方法吧 socket.h #ifndef SOCKET_H #define SOCKET_…

Linux系统编程(九)线程同步

Linux系统编程&#xff08;九&#xff09;线程同步一、什么是线程同步&#xff1f;二、互斥量三、条件变量pthread_cond_wait函数pthread_cond_signal函数生产者和消费者模型一、什么是线程同步&#xff1f; 线程同步&#xff0c;指一个线程发出某一功能调用时&#xff0c;在没…

linux网络编程(一)网络基础传输知识

linux网络编程&#xff08;一&#xff09;网络传输基础知识一、什么是协议&#xff1f;二、使用步骤典型协议2.网络应用程序设计模式C/S模式B/S模式优缺点3.分层模型4.TCP/IP四层模型通信过程5.协议格式数据包封装以太网帧格式ARP数据报格式IP段格式UDP数据报格式TCP数据报格式…

Linux 进程学习(四)------ sigaction 函数

转自&#xff1a;http://www.cnblogs.com/wblyuyang/archive/2012/11/13/2768923.html 使用 sigaction 函数&#xff1a; signal 函数的使用方法简单&#xff0c;但并不属于 POSIX 标准&#xff0c;在各类 UNIX 平台上的实现不尽相同&#xff0c;因此其用途受 到了一定的限制…

linux网络编程(二)高并发服务器

linux网络编程&#xff08;二&#xff09;高并发服务器错误处理高并发服务器多进程并发服务器客户端错误处理 #include "wrap.h"int Bind(int fd, const struct sockaddr* sa, socklen_t salen) {int ret;if ((ret bind(fd, sa, salen)) < 0){perror("bind…

linux知识(一) 程序、进程与线程

linux知识&#xff08;一&#xff09; 程序、进程与线程程序进程程序如何变成进程&#xff1f;线程线程与进程fork和创建新线程的区别优点程序 程序&#xff1a;程序是已编译好的二进制文件&#xff0c;存储在磁盘中&#xff0c;不占用系统资源 程序包括&#xff1a; RO段&am…

linux知识(二)互斥量、信号量和生产者消费者模型

linux知识&#xff08;二&#xff09;互斥量、信号量和生产者消费者模型一、互斥量产生原因二、信号量生产者消费者模型一、互斥量 产生原因 使用多线程常常会碰到数据混乱的问题&#xff0c;那么使用互斥量&#xff0c;相当于“加锁”的操作&#xff0c;将有助于解决数据混乱…

基于Linux的Socket编程之TCP全双工Server-Client聊天程序

转载&#xff1a;http://blog.csdn.net/apollon_krj/article/details/53437764#0-tsina-1-58570-397232819ff9a47a7b7e80a40613cfe1 一、引言&#xff1a; 由于accept函数、read、write、recv、send等函数都是是阻塞式的&#xff0c;在同一个进程之中&#xff0c;只要有任何一个…

数据结构(一)线性表

数据结构&#xff08;一&#xff09;线性表一、线性表定义二、顺序表定义动态数组三、单链表定义不带头结点带头结点头结点与不带头结点的区别头插法与尾插法双链表循环链表循环单链表循环双链表静态链表一、线性表定义 线性表是具有相同数据类型的n个数据元素的有限序列 特点…

linux网络编程(二)TCP通讯状态

linux网络编程&#xff08;二&#xff09;TCP通讯状态TCP状态转换为什么需要等待2MSL&#xff1f;端口复用TCP状态转换 tcp协议连接开始会经过三次握手&#xff0c;客户端和服务器开始都会处于CLOSED状态 第一次握手&#xff1a;客户端会先发送SYN请求给服务器&#xff0c;客户…

gethostbyname() 函数说明

转载&#xff1a;http://www.cnblogs.com/cxz2009/archive/2010/11/19/1881611.html gethostbyname()函数说明——用域名或主机名获取IP地址 包含头文件 #include <netdb.h> #include <sys/socket.h> 函数原型 struct hostent *gethostbyna…

Linux socket编程(一) 对套接字操作的封装

转载:http://www.cnblogs.com/-Lei/archive/2012/09/04/2670942.html 以前写的&#xff0c;现在回顾一下&#xff1a; 下面是对socket操作的封装&#xff0c;因为在Linux下写中文到了windows里面会乱码&#xff0c;所以注释用英文来写&#xff0c;有空再查下解决方法吧 socket.…

如何在linux上安装sqlite数据库

如何在linux上安装sqlite数据库一、下载二、解压三、配置&#xff08;configure&#xff09;四、编译和安装五、执行sqlite3程序六、测试代码一、下载 首先要先下载sqlite3源码包 链接&#xff1a;https://pan.baidu.com/s/1_70342ZLlPjLlqGzpy5IHw 提取码&#xff1a;84ne …