为什么C语言用execl执行bash shell脚本会出现Exec format error?

cmykrgb123 2009-11-04 08:41:56
我遇到一个奇怪的问题,用execl函数执行execl("./a.sh","arg0",NULL);会失败,出现“fail to exec: Exec format error”。而如果用execlp("./a.sh","arg0",NULL);就一切正常。而且如果执行的不是./a.sh而是./a.out(一个二进制可执行文件),两者就都没问题。execl和execlp区别难道不仅仅就是在第一个参数不是完整路径名而是文件名时才会在查找范围上有体现吗?


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
pid_t pid;
pid = fork();
if(pid < 0){
printf("fail to fork\n");
exit(1);
}else if(pid == 0){
if(execl("./a.sh","arg0",NULL) < 0){
perror("fail to exec");
exit(0);
}
}
printf("the parent\n");
return 0;
}
...全文
3205 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
cmykrgb123 2009-11-04
  • 打赏
  • 举报
回复
谢谢楼上,这下对exec几个函数理解更深入了一步。
mymtom 2009-11-04
  • 打赏
  • 举报
回复
#! /bin/sh
开头的文件,知道要调用响应的解释器执行.
b.sh就是这种情况.
====
应该是
====
#! /bin/sh
开头的文件,execve知道要调用/bin/sh作为解释器执行.
例子中的a.sh就是
mymtom 2009-11-04
  • 打赏
  • 举报
回复
1. execl和execlp的区别除了路径搜索方面的不同, execlp在文件格式execve返回不是可执行文(ENOEXEC)(楼主的a.sh是shell脚本就不是可执行文件格式)时,会调用shell执行指定的文件.

2. exeve系统调用认识
#! /bin/sh
开头的文件,知道要调用响应的解释器执行.
b.sh就是这种情况.

EXECLP
Some of these functions have special semantics.

The functions execlp(), execvp(), and execvP() will duplicate the actions
of the shell in searching for an executable file if the specified file
name does not contain a slash ``/'' character. For execlp() and
execvp(), search path is the path specified in the environment by
``PATH'' variable. If this variable is not specified, the default path
is set according to the _PATH_DEFPATH definition in <paths.h>, which is
set to ``/usr/bin:/bin''. For execvP(), the search path is specified as
an argument to the function. In addition, certain errors are treated
specially.

If an error is ambiguous (for simplicity, we shall consider all errors
except ENOEXEC as being ambiguous here, although only the critical error
EACCES is really ambiguous), then these functions will act as if they
stat the file to determine whether the file exists and has suitable exe-
cute permissions. If it does, they will return immediately with the
global variable errno restored to the value set by execve(). Otherwise,
the search will be continued. If the search completes without performing
a successful execve() or terminating due to an error, these functions
will return with the global variable errno set to EACCES or ENOENT
according to whether at least one file with suitable execute permissions
was found.

If the header of a file is not recognized (the attempted execve()
returned ENOEXEC), these functions will execute the shell with the path
of the file as its first argument. (If this attempt fails, no further
searching is done.)

The execve() system call transforms the calling process into a new
process. The new process is constructed from an ordinary file, whose
name is pointed to by path, called the new process file. This file is
either an executable object file, or a file of data for an interpreter.
An executable object file consists of an identifying header, followed by
pages of data representing the initial program (text) and initialized
data pages. Additional pages may be specified by the header to be ini-
tialized with zero data; see elf(5) and a.out(5).

EXECVE

An interpreter file begins with a line of the form:

#! interpreter [arg]
mymtom 2009-11-04
  • 打赏
  • 举报
回复
a.sh第一行加
#! /bin/sh


$ cat a.sh
#! /bin/sh
echo $0
date
echo
$ cat b.sh
echo $0
date
echo
$ cat 077.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
pid_t pid;

pid = fork();
if(pid < 0){
printf("fail to fork\n");
exit(1);
}else if(pid == 0){
if(execl("./a.sh","arg0",NULL) < 0){
perror("fail to exec");
}
}

sleep(1);
pid = fork();
if(pid < 0){
printf("fail to fork\n");
exit(1);
}else if(pid == 0){
if(execl("./b.sh","arg0",NULL) < 0){
perror("fail to exec");
exit(1);
}
}

sleep(1);
pid = fork();
if(pid < 0){
printf("fail to fork\n");
exit(1);
}else if(pid == 0){
if(execlp("./a.sh","arg0",NULL) < 0){
perror("fail to exec");
exit(1);
}
}

sleep(1);
pid = fork();
if(pid < 0){
printf("fail to fork\n");
exit(1);
}else if(pid == 0){
if(execlp("./b.sh","arg0",NULL) < 0){
perror("fail to exec");
exit(1);
}
}

sleep(1);
printf("the parent\n");
return 0;
}

/* 输出 */
/*
$ ./077
./a.sh
Wed Nov 4 21:25:38 CST 2009

fail to exec: Exec format error
./a.sh
Wed Nov 4 21:25:40 CST 2009

./b.sh
Wed Nov 4 21:25:41 CST 2009

the parent
*/
源码链接: https://pan.quark.cn/s/a4b39357ea24 在C语言编程环境中,多项式求和是一项常见的编程实践,它融合了数学理论、算法设计以及C语言的基础运用。此类程序可能包含对用户输入的多项式表达式进行解析,进而计算各项的总和。接下来将对这一主题进行深入阐述。 多项式在数学领域是一个基础性概念,它由常数、变量及指数通过线性方式组合而成,例如表达式`3x^2 + 2x - 1`。在C语言环境下,我们可以借助数组来表示多项式的各项系数,例如通过定义一个整型数组`int coefficients[] = {3, 2, -1}`来保存表达式`3x^2 + 2x - 1`的系数值。 1. **多项式解析**: 解析多项式的过程通常需要从用户处获取输入数据,如表达式`3x^2 + 2x - 1`。在C语言中,可以利用`scanf()`函数来接收用户的输入。解析流程涉及到识别每个项的系数、变量及指数,这可能需要运用到字符串处理函数,例如使用`strtok()`函数来分割字符串,以及通过`atoi()`或`atof()`函数将字符串转换为数值类型。 2. **数据结构构建**: 为了高效地处理多项式,可以设计一个结构体用以存储每一项的系数和指数信息。例如: ```c typedef struct { int coefficient; int exponent; } Term; ``` 随后,可以选用链表或数组来存储这些结构体实例,以此来完整表示一个多项式。 3. **求和运算**: 求和操作可能包含两个阶段:(1) 对相同指数的项进行系数相加,(2) 将计算结果整合至最终的多项式表达式中。在处理同次幂项时,需要遍历两个多项式,识别出具有相同指数的项...

23,223

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧