exec族函数、system函数、popen函数、PATH

exec族函数函数的作用:
我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时,该进程被完全替换为新程序(在exec都后面的代码不会被得到执行)。因为调用exec函数并不创建新进程,所以前后进程的ID并没有改变。

exec族函数功能:

在调用进程内部执行一个可执行文件。可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。

函数族:
exec函数族分别是:execl, execlp, execle, execv, execvp, execvpe

函数原型:

#include <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[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);//使用较少

返回值:
exec函数族的函数执行成功后不会返回,调用失败时,会设置errno并返回-1,然后从原程序的调用点接着往下执行。(errno这个值可以通过perror打印出来)

参数说明:

  • path:可执行文件的路径名字
  • arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束,例如:execl("./bin/echoarg",“echoarg”,“abc”,NULL) echoarg是可执行文件名,abc是第一个参数,最后必须以NULL结尾。
  • file:如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录中搜寻可执行文件。

exec族函数参数极难记忆和分辨,函数名中的字符会给我们一些帮助:

  • l : 使用参数列表
  • p:使用文件名,并从PATH环境进行寻找可执行文件
  • v:应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数。
  • e:多了envp[]数组,使用新的环境变量代替调用进程的环境变量

字符串转整型:

#include <stdlib.h>
int atoi(const char *nptr);
long atol(const char *nptr);
long long atoll(const char *nptr);

示例代码:

****execl代码****
#include<stdio.h>
#include <unistd.h>
int main()
{printf("before execl");if(execl("./number","number","12","13",NULL)==-1){printf("execl fail\n");perror("because");}printf("after execl");//因为execl函数调用成功所以它之后的代码就不再执行。return 0;
}****number可执行文件代码:****
#include<stdio.h>
#include <stdlib.h>
int main(int agrc,char*argv[3])
{printf("参数和为:%d\n",atoi(argv[1])+atoi(argv[2]));return 0;
}可以通过whereis ls查看ls可执行程序的位置:
上述程序中就可以替换为下列代码——执行ls即可
execl("ls路径","ls",NULL);
想用ls -l就可以在ls后面加参数即可:
execl("ls路径","ls","-l",NULL);获取系统服务时间指令:date
同样的道理可以用whereis date查看date可执行程序的路径
上述程序中就可以替换为下列代码——执行date即可
execl("date路径","date",NULL);

execl和execlp的区别在于:

exaclp函数带p,所以能通过环境变量PATH查找到可执行文件ps,当可执行文件的文件路径中带有 / 这种路径符号,我们将其视为路径名(就是按照这个路径去找可执行文件),否则就将其视为环境变量(path变量的作用是可以让我们在没有这个应用的路径下面打开我们需要打开的应用,前提是这个应用得在环境变量里面配置了路径),在linux系统中可以用 echo $PATH 查看当前的环境变量,那些冒号是分隔符。如果用execlp就可以写为execlp(“date”,“date”,NULL);直接写date就好。

环境变量和pwd显示的路径不一样,只有将当前路径加入到环境变量的时候,环境变量里面才会出现当前路径,也就意味着在任何路径下都可以访问该路径下的可执行文件。

PATH是什么?

如何修改环境变量?
在linux环境中可以通过以下代码将路径加入到环境变量:

方法一:
export PATH=$PATH:当前路径
$PATH表示当前环境变量
//配置完后可以通过echo $PATH查看配置结果。
生效方法:立即生效
有效期限:临时改变,只能在当前的终端窗口中有效,当前窗口关闭后就会恢复原有的path配置
用户局限:仅对当前用户方法二:
通过修改.bashrc文件:
vim ~/.bashrc
//在最后一行添上:
export PATH=/usr/local/mongodb/bin:$PATH
生效方法:(有以下两种)
1、关闭当前终端窗口,重新打开一个新终端窗口就能生效
2、输入“source ~/.bashrc”命令,立即生效
有效期限:永久有效
用户局限:仅对当前用户方法三:
通过修改profile文件:
vim /etc/profile
/export PATH //找到设置PATH的行,添加
export PATH=/usr/local/mongodb/bin:$PATH
生效方法:系统重启
有效期限:永久有效
用户局限:对所有用户方法四:
通过修改environment文件:
vim /etc/environment
在PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games”中加入“:/usr/local/mongodb/bin”
生效方法:系统重启
有效期限:永久有效
用户局限:对所有用户

带v不带l的一类exec函数:

其实就是将execl可执行程序里面的餐数放到指针数组里面,然后用数组的首地址代替可执行程序名字和程序的参数。

示例:

char* canshu[]={"number","12","13","NULL"};
execv("./number",canshu)

exec配合fork使用:

实现功能当父进程检测到输入为1的时候后,创建子进程把配置文件的字段修改掉。

***********************
以下是存在父子进程的程序
通过调用现有的可执行程序
修改目标文件的内容,他这个
要修改文件要加上绝对路径
************************
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include<stdlib.h>
#include <sys/wait.h>
int main()
{pid_t pid;pid_t fpid,returnpid;int status;int input=0;int execlreturn=0;while(1){printf("请输入数字:\n");scanf("%d",&input);if(input==1){fpid=fork();if(fpid>0){returnpid=waitpid(fpid,&status,0);if(WIFEXITED(status)){printf("子进程正常退出,退出参数是:%d\n",WEXITSTATUS(status));}}if(fpid==0){execlreturn=execl("/home/fhn/linuxfile/changfile","changfile","/home/fhn/linuxfile/test.txt",NULL);            if(execlreturn==-1){printf("exec fail\n");perror("execfail");}}}else{printf("do nothing\n");}}return 0;
}

system函数:

#include <stdlib.h>
int system(const char *command);函数说明:
system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令
此命令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。sh -c就相当于./  就是为了执行后面的指令string返回值:
如果fork()失败 返回-1:出现错误如果exec()失败,表示不能执行Shell,返回值相当于Shell执行了exit(127)如果执行成功则返回子Shell的终止状态如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),则返回非零值。如果system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为 system()调用/bin/sh失败所返回的127,因此最好能再检查errno 来确认执行成功。system调用结束后还会返回原程序继续执行system下面的代码,而exec族函数不会。我的理解:
在system函数调用成功时返回进程的状态值
当因shell不能执行时也就是system()在调
用/bin/sh时失败时返回127,其他失败情况
返回-1,命令string为空指针(NULL)system
函数的返回值很简单明了,只有01。返回1,
表明系统的命令处理程序,即/bin/sh是可用的。
相反,如果命令处理程序不可用,则返回0。 在
判断返回值时最好能再检查errno来确认执行成功使用例子:
system("/home/fhn/linuxfile/changfile /home/fhn/linuxfile/test.txt");

popen函数和system函数区别?

popen函数:

#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);

函数说明:

  • popen()会调用fork()产生子进程,然后从子进程中调用/bin/sh -c来执行参数command的指令。
  • 参数type可使用“r”代表读取,“w”代表写入。依照此type值,popen()会建立管道连到子进程的标准输出设备(比如说:ps指令,所以可以用“”r“”根据返回的指针读取子进程的标准输出内容)或标准输入设备,然后返回一个文件指针。随后进程便可利用此文件指针来读取子进程的输出设备或是写入到子进程的标准输入设备中。
  • 此外,所有使用文件指针(FILE*)操作的函数也都可以使用,除了fclose()以外。
  • 如果 type 为 r,那么调用进程读进 command 的标准输出。如果 type 为 w,那么调用进程写到 command 的标准输入。
  • popen比sysytem的好处是可以通过管道获取运行结果

返回值:
若成功则返回文件指针,否则返回NULL,错误原因存于errno中。
注意:
popen()会继承环境变量,通过环境变量可能会造成系统安全的问题。

为什么要用popen函数:

#include<stdio.h>
#include <stdlib.h>
int main()
{system("ps");return 0;
}这几行代码的运行结果如下:
fhn@ubuntu:~/jincheng$ ./popen PID TTY          TIME CMD20157 pts/3    00:00:03 bash24755 pts/3    00:00:00 popen24756 pts/3    00:00:00 sh24757 pts/3    00:00:00 ps如果想要把它运行的结果放到文件或者字符串中去
就要用到popen函数将结果流入到文件中去,如下面代码:
#include<stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{char* buf;FILE* fd;int n_read;buf=(char*)malloc(1024);fd=popen("ps","r");n_read=fread(buf,1,1024,fd);pclose(fd);printf("管道输出:%s",buf);return 0;
}
以下是输出结果:fhn@ubuntu:~/jincheng$ ./popen 
管道输出:   PID TTY          TIME CMD20157 pts/3    00:00:03 bash24865 pts/3    00:00:00 popen24866 pts/3    00:00:00 sh24867 pts/3    00:00:00 ps如果有将信息流入到内存而不打印则屏幕上面没有显示。

注意popen用的是fread、fwrite而不是read和write,因为read返回的是文件描述符不符合,fread返回的是文件指针

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

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

相关文章

jquery.validate.unobtrusive的使用

应用 一、引入 <script src"Scripts/jquery-1.7.1.min.js"></script> <script src"Scripts/jquery.validate.js"></script> <script src"Scripts/jquery.validate.unobtrusive.js"></script> 二、1&#xf…

Linux操作系统六大优点

❤️作者主页&#xff1a;IT技术分享社区 ❤️作者简介&#xff1a;大家好,我是IT技术分享社区的博主&#xff0c;从事C#、Java开发九年&#xff0c;对数据库、C#、Java、前端、运维、电脑技巧等经验丰富。 ❤️个人荣誉&#xff1a; 数据库领域优质创作者&#x1f3c6;&#x…

[webview] 放大缩小的问题

http://www.cocoachina.com/bbs/read.php?tid33249转载于:https://www.cnblogs.com/zxykit/p/5274831.html

进程间通信IPC(一)(半双工管道和消息队列)

引言&#xff1a; 之前学习的进程之间交换信息的方法只能由fork或exec传送打开文件&#xff0c;或者文件系统。但是这种通讯方式有局限性&#xff0c;接下来将说明进程之间相互通信的其他技术——IPC(InterProcessCommunication)&#xff0c;过去UNIX系统IPC是各种进程间通信方…

Seata相关概念

相关概念 XID&#xff1a;一个全局事务的唯一标识 Transaction Coordinator (TC)&#xff1a; 事务协调器&#xff0c;维护全局事务的运行状态&#xff0c;负责协调并驱动全局事务的提交或回滚&#xff08;可以理解为事务的协调者&#xff09;。 Transaction Manager (TM)&…

VSS配置

http://www.cnblogs.com/FreeDong/articles/2193151.html转载于:https://www.cnblogs.com/lacey/p/5275514.html

Program terminated with signal SIGSEGV, Segmentation fault.

问题&#xff1a; 在程序运行时出现了&#xff1a;Segmentation fault (core dumped)&#xff0c;分段故障(堆芯转储)也就是段错误。 我首先在一篇博客上面找到如何使用gdb调试&#xff1a; 1、首先使用ulimit -a查看你的core file size是否为0.如果不是的话就请跳到步骤3&am…

NFS简介

NFS 是Network File System的缩写&#xff0c;即网络文件系统。一种使用于分散式文件系统的协定&#xff0c;由Sun公司开发&#xff0c;于1984年向外公布。功能是通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据&#xff0c;让应用程序在客户端通过网络访问位于服…

Php Laravel框架 多表关系处理 之 Eloquent一对多关系处理

Php Laravel框架 多表关系处理 之 Eloquent一对多关系处理 本博文主要介绍 Laravel 框架中 Eloquent 对一对多关系的处理以及在 Laravel Administrator(后台扩展包)中的应用。 您的数据库可能是彼此相关的。比方&#xff0c;一篇博客文章可能有很多评论&#xff0c;或者一个订…

进程间通信IPC(二)(共享内存、信号、信号量)

共享内存&#xff1a; 共享内存就是允许两个或多个进程共享一定的存储区。就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候&#xff0c;其它进程都会察觉到这个更改。因为数据不需要在客户机和服务器端之间复制&am…

分布式理论CAP定理

CAP原则又称CAP定理&#xff0c;指的是在一个分布式系统中&#xff0c; Consistency&#xff08;一致性&#xff09;、 Availability&#xff08;可用性&#xff09;、Partition tolerance&#xff08;分区容错性&#xff09;&#xff0c;三者不可兼得。 998年&#xff0c;加州…

xmlWriter 以UTF-8格式写xml问题

dom4j中的XMLWriter提供以下几种构造方法&#xff1a; XMLWriter() XMLWriter(OutputFormat format) XMLWriter(OutputStream out) XMLWriter(OutputStream out, OutputFormat format) XMLWriter(Writer writer) XMLWriter(Writer writer, OutputFormat format) 最简单常…

linux线程(互斥锁、条件)

线程概念&#xff1a; 典型的UNIX/Linux进程可以看成只有一个控制线程&#xff1a;一个进程在同一时刻只做一件事情。有了多个控制线程后&#xff0c;在程序设计时可以把进程设计成在同一时刻做不止一件事&#xff0c;每个线程各自处理独立的任务。 进程是程序执行时的一个实例…

centos下防火墙设置

1、开启防火墙 systemctl start firewalld2、开放指定端口firewall-cmd --zonepublic --add-port8888/tcp --permanent命令含义&#xff1a; --zone #作用域 --add-port1935/tcp #添加端口&#xff0c;格式为&#xff1a;端口/通讯协议 --permanent #永久生效&#xff0c;没有…

linux网络编程、socket编程

进程间通信&#xff1a; 特点&#xff1a;依赖于内核&#xff0c;造成缺陷——无法实现多机通信。 网络&#xff1a; 地址&#xff1a;由IP地址&#xff08;IP地址是IP协议提供的一种统一的地址格式&#xff0c;它为互联网上的每一个网络和每一台主机分配一个逻辑地址&#xf…

【Python】Python Mako模板使用

参考资料&#xff1a; Mako Templates for Python官网&#xff1a;http://www.makotemplates.org/ Python模板库Mako的用法&#xff1a;http://my.oschina.net/u/877170/blog/290438 Mako 1.0.4 Documentation&#xff1a;http://docs.makotemplates.org/en/latest/usage.html#…

简单的ftp服务器(客户端、服务器端、socket)

查看本机IP地址&#xff1a; 127.0.0.1 服务器功能&#xff1a; 可以获取服务器文件使用get指令可以展示服务器有哪些文件使用ls指令进入服务器某个文件夹使用指令cd文件夹名称上传本地文件到服务器&#xff0c;使用指令putpwd可以查看客户端在当前服务器的位置 客户端本地…