一、exec族
当进程调用一种 exec 函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用 exec 并不创建新进程,所以调用 exec 前后该进程的 id 并未改变。exec族有以下:
#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[]);
为了方便记忆,分开以下几点来记忆:
- l:使用参数列表
- p:使用文件名,以文件名的方式查找可执行文件,系统会自动从 $PATH 查找
- v:应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数
- e:多了 envp[ ] 数组,使用新的环境变量代替调用进程的环境变量
参数说明:
- path:可执行文件的路径名字,例如:当前路径下的可执行文件,
./a.out - arg:可执行程序所带的参数,第一个参数为可执行文件的名字,没有带路径且 arg 必须以 NULL 结束,例如:复制文件的指令,后面带的参数,
cp file1 file2 - file:如果参数 file 中包含 /,则将其视为路径名,否则就按 path 环境变量,在它所指定的各目录中搜寻可执行文件
返回值:
exec 函数族的函数执行成功后不会返回,调用失败时,会设置 errno 并返回 -1,然后从原程序的调用点接着往下执行。
1.1.execl
使用 execl 函数实现ls -l列出长格式目录:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);
int main(void)
{
printf("Before execl\n");
if(execl("/bin/ls", "ls", "-l", NULL) == -1) //第一个参数是文件名,第二个参数是-l
{
printf("execl failed!\n");
perror("why"); //该函数会显示出错误的信息
}
printf("After execl\n");
return 0;
}
1.2.execlp
该函数与上面的 execl 函数类似,只是不需要填写整个文件路径:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execlp(const char *file, const char *arg, ...);
int main(void)
{
printf("Before execl\n");
if(execlp("ls", "ls", "-l", NULL) == -1)
{
printf("execl failed!\n");
perror("why"); //该函数会显示出错误的信息
}
printf("After execl\n");
return 0;
}
1.3.execvp
带 v 字母的 exec 族,使用之前需要创建一个数组用来装载程序的参数:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execvp(const char *file, char *const argv[]);
int main(void)
{
printf("Before execl\n");
char *argv[] = {"ls", "-l", NULL}; //字符串指针数组
if(execvp("ls", argv) == -1)
{
printf("execl failed!\n");
perror("why"); //该函数会显示出错误的信息
}
printf("After execl\n");
return 0;
}
二、软件实现
在父进程里创建一个子进程,并在子进程里调用 execl 函数,运行新程序,新程序修改文件:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
int main()
{
pid_t pid;
int data = 0;
while(1)
{
printf("Please input your data:\n");
scanf("%d", &data);
if(data == 1)
{
pid = fork();
if(pid > 0)
{
printf("This is the father\n");
wait(NULL);
}
if(pid == 0)
{
execl("./exchange", "exchange", "Text.config", NULL);
exit(0);
}
}
else
{
printf("Again\n");
}
}
return 0;
}
下面是 exchange.c 文件:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int fd, size;
char *readBuf = NULL;
fd = open(argv[1], O_RDWR);
size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
readBuf = (char *)malloc(sizeof(char) * size);
read(fd, readBuf, size);
char *p = strstr(readBuf, "lyy="); //该函数可以寻找该字符串第一次出现的位置
if(p == NULL)
{
printf("Can't Find the signal\n");
exit(-1);
}
p = p + strlen("lyy="); //偏移lyy=个位置
*p = '9'; //使用字符修改
lseek(fd, 0, SEEK_SET);
write(fd, readBuf, strlen(readBuf));
close(fd);
return 0;
}
编译 exchange.c 文件并生成文件名为 exchange 可执行文件

下面是 Text.config 文件的内容:

370

被折叠的 条评论
为什么被折叠?



