文章目录
一、exec族函数
为什么要使用exec族函数,有什么作用
linux进程—exec族函数(execl, execlp, execle, execv, execvp, execvpe)_云英的博客-CSDN博客
从第二个角度来讲
答:执行一个不同的程序。
exec族函数函数的作用:
我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序。
当进程调用exec函数时,该进程被完全替换为新程序。因为调用exec函数并不创建新进程,所以前后进程的ID并没有改变。
#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,然后从源程序的调用点接着往下执行。
参数说明:
- path:可执行文件的路径名字
- arg:可执行程序所带的参数,第一个参数为可执行文件的名字,没有带路径且必须以NULL结束
- file:如果file中包含/,则将其视为路径名,否则就将其按环境变量处理,在它所指定的目录中搜寻可执行文件。
execl函数
execl函数就是,第一个参数是程序的path,最后一个参数是NULL。第二个参数为程序名,其余中间可以放不同数量的参数作为想执行程序参数。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
//int execl(const char *path, const char *arg, ... (char *) NULL );
int main()
{
printf("before execl");
if(execl("./echoarg", "echoarg", "abc", "n", NULL) == -1)
{
printf("execl failed!\n");
}
printf("after execl");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);
int main(int argc, char *argv[])
{
int i = 0;
for (i=0; i<argc; i++){
printf("argv[%d]:%s\n", i, argv[i]);
}
return 0;
}
调用成功不会执行之下的其它代码,替换原来进程,pid号不变。
使用execl调用ls指令
查看ls指令在那个path中:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
//int execl(const char *path, const char *arg, ... (char *) NULL );
int main()
{
printf("before execl\n");
if(execl("/bin/ls", "ls", "-l", NULL) == -1)
{
printf("execl failed!\n");
perror("why");
}
printf("after execl\n");
return 0;
}
exec好处:
需求让你获取系统时间。直接调用系统指令,便捷可节省时间。
exec获取时间
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
//int execl(const char *path, const char *arg, ... (char *) NULL );
int main()
{
printf("this pro get sys time\n");
if(execl("/bin/date", "date", NULL) == -1)
{
printf("execl failed!\n");
perror("why");
}
printf("after execl\n");
return 0;
}
找不到系统路径路径?execlp来帮忙
execlp多于execl的p就是path的意思,多的p能从环境变量中查找指令
使用execl
int main()
{
if(execl("ps", "ps", NULL) == -1)
{
printf("execl failed!\n");
perror("why");
}
return 0;
}
使用execlp
int main()
{
if(execlp("ps", "ps", NULL) == -1)
{
printf("execl failed!\n");
perror("why");
}
return 0;
}
扩展环境变量
同execlp结果一样的execvp仅仅是使用不一样而已
仅仅是把参数放入一个指针数组里
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
//int execl(const char *path, const char *arg, ... (char *) NULL );
int main()
{
char * argv[] = {"ps", NULL};
if(execvp("ps", argv) == -1)
{
printf("execl failed!\n");
perror("why");
}
return 0;
}
execv
execv第一个参数需要加绝对路径
二、exec族函数配合fork
需求:实现功能,当父进程检测到输入为1时,创建子进程把配置文件的字段值修改掉。
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
pid_t pid;
int data = 10;
while(1){
printf("please input a data:");
scanf("%d", &data);
if(data == 1){
pid = fork();
if(pid > 0)
{
wait(NULL);
}
else if(pid == 0)
{
int fd;
char *readBuf=NULL;
fd = open(argv[1], O_RDWR);
/*
int num = lseek(fd, 0, SEEK_CUR);
printf("how many %d\n", num);//0
*/
int size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
readBuf = (char *)malloc(size + 8);
int n_read = read(fd, readBuf, size);
char *p = strstr(readBuf, "LENG=");//修改5为其他
if(p==NULL){
printf("not found]\n");
exit(-1);
}
p = p + strlen("LENG=");
*p = '9';
lseek(fd, 0, SEEK_SET);
int n_write = write(fd, readBuf, strlen(readBuf));
close(fd);
exit(0);
}
}else{
printf("wait, do nothing\n");
}
}
return 0;
}
利用exec函数修改配置文件
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(int argc, char* argv[])
{
pid_t pid;
int data = 10;
while(1){
printf("please input a data:");
scanf("%d", &data);
if(data == 1){
pid = fork();
if(pid > 0)
{
wait(NULL);
}
else if(pid == 0)
{
execl("./changeData", "changeData", "test.config", NULL);
exit(0);//调用exec成功则无用
}
}else{
printf("wait, do nothing\n");
}
}
return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if(argc != 2){
printf("param error\n");
exit(-1);
}
int fd;
char *readBuf=NULL;
fd = open(argv[1], O_RDWR);
/*
int num = lseek(fd, 0, SEEK_CUR);
printf("how many %d\n", num);//0
*/
int size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
readBuf = (char *)malloc(size + 8);
int n_read = read(fd, readBuf, size);
// modify
char *p = strstr(readBuf, "LENG=");//修改5为其他
p = p + strlen("LENG=");
*p = '9';
lseek(fd, 0, SEEK_SET);
int n_write = write(fd, readBuf, strlen(readBuf));
close(fd);
return 0;
}
三、system函数
linux system函数详解 - 南哥的天下 - 博客园
system()函数的返回值如下: 成功,则返回进程的状态值; 当sh不能执行时,返回127; 失败返回-1;
执行指令的方式:(两种)
返回值
如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),则返回非零值。如果 system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为system()调用/bin/sh失败所返回的127,因此最好能再检查errno 来确认执行成功。
调用system代码:
使用system也能修改配置文件的值
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(int argc, char* argv[])
{
pid_t pid;
int data = 10;
while(1){
printf("please input a data:");
scanf("%d", &data);
if(data == 1){
pid = fork();
if(pid > 0)
{
wait(NULL);
}
else if(pid == 0)
{
//execl("./changeData", "changeData", "test.config", NULL);
system("changeData test.config");
}
}else{
printf("wait, do nothing\n");
}
}
return 0;
}
system最后还是会返回到原始程序中执行原来的代码“after system”
system返回值比较奇怪吗???
为什么时32512???
原因在这:
system函数返回值探究_天一涯的博客-CSDN博客
system函数返回值探究-Bean_lee-ChinaUnix博客
四、popen函数
函数原型
参考博文:
linux下popen的使用心得_linux popen结束了能读到吗_libinbin_1014的博客-CSDN博客
比system在应用中的好处:可以获取运行的输出结果
前言
想要获取system输出,通过网络发送出去(其它用途),应该如何实现?
直接system不能获取输出
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
//int execl(const char *path, const char *arg, ... (char *) NULL );
int main()
{
system("ps");
return 0;
}
使用popen,获取程序运行的输出
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
//int execl(const char *path, const char *arg, ... (char *) NULL );
int main()
{
char ret[1024] = {0};//开辟一兆内存空间
FILE* fp = NULL;
fp = popen("ps", "r");
int n_read = fread(ret, 1, 1024, fp);
printf("read %d bytes, ret=\n%s\n", n_read, ret);
return 0;
}