哪位长清仁兄大人解释一下execle函数

EXCEL2010产品密钥,急需能用的excel2010产品激活密钥,在线等30分钟,谢..._百度知道
EXCEL2010产品密钥,急需能用的excel2010产品激活密钥,在线等30分钟,谢...
希望能帮到你自己去搜,有的是啊。excel只是office里面的一个组件,而不是excel。但是你要搜office2010密钥
恩,好的,谢谢你!
来自团队:
其他类似问题
为您推荐:
其他2条回答
这位仁兄,microsoft office 2010 系列的都只有三个月的试用期
试用期过了还会卡,哎,愁,
可以使用破解工具破解一下,百度一下有很多。
excel2010的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁linux下execl()进程管理函数的参数理解_百度知道
linux下execl()进程管理函数的参数理解
这个希望以char* envp[]={&bin&src分别有什么作用,0},再者execle()函数的话新加的环境变量参数又是用来干什么的呢;src”,-为例解释一下,/bin/ls”;usr&#47, “/希望有人可以指点参数ls,“ls”, (char*)0), “-al”;;usr/PATH=&#47,多谢以execl(“&#47
提问者采纳
,1。, ls,-bin&#47。。。。环境变量的意思就是环境变量。接下去的依次是shell里面的参数0。。&#47。;ls 是执行文件
就是那些个参数都是什么意思?有什么意义。。还有环境变量你可以拿那个例子说一下吗?
你在shell里面输入的值从第一个到最后一个,依次是参数0,1...n在没有用绝对路径定位执行文件的时候,系统会在环境变量表示的几个路径中寻找这个可执行文件
提问者评价
谢谢你的耐心解答,好详细呀
其他类似问题
为您推荐:
进程管理的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁Posts - 38,
Articles - 5,
Comments - 34
如果离成功只有一步之遥,那谁都会咬牙坚持下来;如果忽然发现距离很远,那谁都会放弃。而关键的一咬牙,上了一个层次,有人就会春风得意,越活越成功;有人没上去,永远在苦逼中挣扎求生存。然后想,原来在当时,我们俩的距离才那么近。
12:12 by Rudrj2, ... 阅读,
在网上搜了很久都没有一个很好的解释,都只说了一方面system调用子进程后继续执行父进程,execv是调用一个新的进程,所以打算自己读读这两个执行文件源码,自己再找找其他不同:
相关函数: fork,execl,execle,execlp,execv,execvp
表头文件: #include&unistd.h&
定义函数: int execve(const char * filename,char * const argv[ ],char * const envp[ ]);
函数说明: execve()用来执行参数filename字符串所代表的文件路径,第二个参数系利用数组指针来传递给执行文件,最后一个参数则为传递给执行文件的新环境变量数组。
如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno 中。
1. 欲执行的文件不具有用户可执行的权限。
2. 欲执行的文件所属的文件系统是以noexec 方式挂上。
3.欲执行的文件或script翻译器非一般文件。
1.进程处于被追踪模式,执行者并不具有root权限,欲执行的文件具有SUID 或SGID 位。
2.欲执行的文件所属的文件系统是以nosuid方式挂上,欲执行的文件具有SUID 或SGID 位元,但执行者并不具有root权限。
E2BIG 参数数组过大
ENOEXEC 无法判断欲执行文件的执行文件格式,有可能是格式错误或无法在此平台执行。
EFAULT 参数filename所指的字符串地址超出可存取空间范围。
ENAMETOOLONG 参数filename所指的字符串太长。
ENOENT 参数filename字符串所指定的文件不存在。
ENOMEM 核心内存不足
ENOTDIR 参数filename字符串所包含的目录路径并非有效目录
EACCES 参数filename字符串所包含的目录路径无法存取,权限不足
ELOOP 过多的符号连接
ETXTBUSY 欲执行的文件已被其他进程打开而且正把数据写入该文件中
EIO I/O 存取错误
ENFILE 已达到系统所允许的打开文件总数。
EMFILE 已达到系统所允许单一进程所能打开的文件总数。
EINVAL 欲执行文件的ELF执行格式不只一个PT_INTERP节区
EISDIR ELF翻译器为一目录
ELIBBAD ELF翻译器有问题。
#include&unistd.h&
  char * argv[ ]={&ls&,&-al&,&/etc/passwd&,(char *)0};
  char * envp[ ]={&PATH=/bin&,0}
  execve(&/bin/ls&,argv,envp);
-rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd
下面是system执行文件代码:
相关函数: fork,execve,waitpid,popen
表头文件: #i nclude&stdlib.h&
定义函数: int system(const char * string);
函数说明: system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命&令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。
返回值: =-1:出现错误
=0:调用成功但是没有出现子进程
&0:成功退出的子进程的id
如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),则返回非零值&。 如果system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为 system()调用/bin/sh失败所返回的127,因此最好能再检查errno 来确认执行成功。
附加说明: 在编写具有SUID/SGID权限的程序时请勿使用system(),system()会继承环境变量,通过环境变量可能会造成系统安全的问题。
#include&stdlib.h&
  system(&ls -al /etc/passwd /etc/shadow&);
执行结果:
-rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd
-r--------- 1 root root 572 Sep 2 15 :34 /etc/shado
char tmp[];
sprintf(tmp,"/bin/mount -t vfat %s /mnt/usb",dev);
system(tmp);
其中dev是/dev/sda1。
system源码
int system(const char * cmdstring)
if(cmdstring == NULL){
return (1);
if((pid = fork())&0){
status = -1;
else if(pid == 0){
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
-exit(127); //子进程正常执行则不会执行此语句
while(waitpid(pid, &status, 0) & 0){
if(errno != EINTER){
status = -1;
先分析一下原理,然后再看上面的代码大家估计就能看懂了:&&&当system接受的命令为NULL时直接返回,否则fork出一个子进程,因为fork在两个进程:父进程和子进程中都返回,这里要检查返回的pid,fork在子进程中返回0,在父进程中返回子进程的pid,父进程使用waitpid等待子进程结束,子进程则是调用execl来启动一个程序代替自己,execl("/bin/sh", "sh", "-c", cmdstring,(char*)0)是调用shell,这个shell的路径是/bin/sh,后面的字符串都是参数,然后子进程就变成了一个shell进程,这个shell的参数是cmdstring,就是system接受的参数。在windows中的shell是command,想必大家很熟悉shell接受命令之后做的事了。&&&如果上面的你没有看懂,那我再解释下fork的原理:当一个进程A调用fork时,系统内核创建一个新的进程B,并将A的内存映像复制到B的进程空间中,因为A和B是一样的,那么他们怎么知道自己是父进程还是子进程呢,看fork的返回值就知道,上面也说了fork在子进程中返回0,在父进程中返回子进程的pid。execl是编译器的函数(在一定程度上隐藏具体系统实现),在linux中它会接着产生一个linux系统的调用execve, 原型见下:&&&&int execve(const char * file,const char **argv,const char **envp);&&&看到这里你就会明白为什么system()会接受父进程的环境变量,但是用system改变环境变量后,system一返回主函数还是没变,原因从system的实现可以看到,它是通过产生新进程实现的,从我的分析中可以看到父进程和子进程间没有进程通信,子进程自然改变不了父进程的环境变量。
system调用最终依然是依靠execve()实现调用的,那么分析下execve:
典型的用法,就是在shell中,执行一个文件,比如说,一个编译好的文件,叫做helloworld,那么,在shell下执行./helloworld的时候,shell就去fork()一个子进程,然后在子进程里面execve("./helloworld",NULL,NULL);
这样,就执行了这个文件!
在shell中:
if(!fork())
execve("./helloworld",NULL,NULL);
那么,这个execve函数,都做了什么,追一下内核看看!
首先,利用参数(文件名),调用函数namei(filename),能取得这个文件名对应的i节点!
然后把当前进程(子进程)的i节点置成上面取得的那个i节点。
释放所有资源,释放内存页表并且修改LDT。
凶狠的把中断压入的EIP的值都给改了,改成了从上面那个i节点读出的可执行文件的头部那个文件执行的头字段。
更猛的是,把栈也给改了!
好了,这下子跟父进程一点关系都没有了!
中断返回后,程序从i节点指向的那个可执行程序开始执行!
这里,我们注意到个问题!
execve之后,原来的那些代码,都没了,也就是说,上面的那个exit(0),根本执行不到那!因为在execve调用中,代码就换成了那个i节点的了,以前的那些,都释放了!牛!
#include &stdio.h&
#include &unistd.h&
int main()
execve("./helloworld",NULL,NULL);
printf("nothing!\n");
这个程序输出什么?(假设helloworld程序输出hello world!)
那么,这个程序输出的,就是hello world!
你会想,为什么没有下面的nothing!啊?
因为,execve调用中,这些代码都没有了,代码被替换成helloworld的了,而且,只执行helloworld就完了!
那么,你会说,那怎么执行完helloworld后,继续做事啊?
  #include &stdio.h&
  #include &unistd.h&
  int main()
    if(!fork())
      execve("./helloworld",NULL,NULL);
    else
      printf("nothing!\n");
    return 0;
执行一下,绝大多数会输出hello world!后,输出nothing!
这个execve够变态!
下面是找的一个比较好的解释,有时间再慢慢研究:
1 //execve()系统中断调用函数。加载并执行子进程(其它程序)。
2 // 该函数系统中断调用(int 0x80)功能号__NR_execve 调用的函数。
3 // 参数:eip - 指向堆栈中调用系统中断的程序代码指针eip 处,参见kernel/system_call.s 程序
4 // 开始部分的说明;tmp - 系统中断调用本函数时的返回地址,无用;
5 // filename - 被执行程序文件名;argv - 命令行参数指针数组;envp - 环境变量指针数组。
6 // 返回:如果调用成功,则不返回;否则设置出错号,并返回-1。
8 do_execve (unsigned long *eip, long tmp, char *filename,
char **argv, char **envp)
struct m_inode *
// 内存中I 节点指针结构变量。
struct buffer_head *
// 高速缓存块头指针。
// 执行文件头部数据结构变量。
unsigned long page[MAX_ARG_PAGES];
// 参数和环境字符串空间的页面指针数组。
int i, argc,
int e_uid, e_
// 有效用户id 和有效组id。
// 返回值。
int sh_bang = 0;
// 控制是否需要执行脚本处理代码。
19 // 参数和环境字符串空间中的偏移指针,初始化为指向该空间的最后一个长字处。
unsigned long p = PAGE_SIZE * MAX_ARG_PAGES - 4;
22 // eip[1]中是原代码段寄存器cs,其中的选择符不可以是内核段选择符,也即内核不能调用本函数。
if ((0xffff & eip[1]) != 0x000f)
panic ("execve called from supervisor mode");
25 // 初始化参数和环境串空间的页面指针数组(表)。
for (i = 0; i & MAX_ARG_PAGES; i++)
/* clear page-table */
page[i] = 0;
28 // 取可执行文件的对应i 节点号。
if (!(inode = namei (filename)))
/* get executables inode */
return -ENOENT;
31 // 计算参数个数和环境变量个数。
argc = count (argv);
envc = count (envp);
35 // 执行文件必须是常规文件。若不是常规文件则置出错返回码,跳转到exec_error2(第347 行)。
36 restart_interp:
if (!S_ISREG (inode-&i_mode))
/* must be regular file */
retval = -EACCES;
goto exec_error2;
42 // 检查被执行文件的执行权限。根据其属性(对应i 节点的uid 和gid),看本进程是否有权执行它。
i = inode-&i_
e_uid = (i & S_ISUID) ? inode-&i_uid : current-&
e_gid = (i & S_ISGID) ? inode-&i_gid : current-&
if (current-&euid == inode-&i_uid)
else if (current-&egid == inode-&i_gid)
if (!(i & 1) && !((inode-&i_mode & 0111) && suser ()))
retval = -ENOEXEC;
goto exec_error2;
55 // 读取执行文件的第一块数据到高速缓冲区,若出错则置出错码,跳转到exec_error2 处去处理。
if (!(bh = bread (inode-&i_dev, inode-&i_zone[0])))
retval = -EACCES;
goto exec_error2;
61 // 下面对执行文件的头结构数据进行处理,首先让ex 指向执行头部分的数据结构。
ex = *((struct exec *) bh-&b_data);
/* read exec-header *//* 读取执行头部分 */
63 // 如果执行文件开始的两个字节为'#!',并且sh_bang 标志没有置位,则处理脚本文件的执行。
if ((bh-&b_data[0] == '#') && (bh-&b_data[1] == '!') && (!sh_bang))
67 * This section does the #! interpretation.
68 * Sorta complicated, but hopefully it will work. -TYT
71 * 这部分处理对'#!'的解释,有些复杂,但希望能工作。-TYT
char buf[1023], *cp, *interp, *i_name, *i_
unsigned long old_
77 // 复制执行程序头一行字符'#!'后面的字符串到buf 中,其中含有脚本处理程序名。
strncpy (buf, bh-&b_data + 2, 1022);
79 // 释放高速缓冲块和该执行文件i 节点。
brelse (bh);
iput (inode);
82 // 取第一行内容,并删除开始的空格、制表符。
buf[1022] = '\0';
if (cp = strchr (buf, '\n'))
*cp = '\0';
for (cp = (*cp == ' ') || (*cp == '\t'); cp++);
89 // 若该行没有其它内容,则出错。置出错码,跳转到exec_error1 处。
if (!cp || *cp == '\0')
retval = -ENOEXEC;
/* No interpreter name found */
goto exec_error1;
95 // 否则就得到了开头是脚本解释执行程序名称的一行内容。
interp = i_name =
97 // 下面分析该行。首先取第一个字符串,其应该是脚本解释程序名,iname 指向该名称。
i_arg = 0;
for (; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
if (*cp == '/')
i_name = cp + 1;
104 // 若文件名后还有字符,则应该是参数串,令i_arg 指向该串。
*cp++ = '\0';
111 * OK, we've parsed out the interpreter name and
112 * (optional) argument.
115 * OK,我们已经解析出解释程序的文件名以及(可选的)参数。
117 // 若sh_bang 标志没有设置,则设置它,并复制指定个数的环境变量串和参数串到参数和环境空间中。
if (sh_bang++ == 0)
p = copy_strings (envc, envp, page, p, 0);
p = copy_strings (--argc, argv + 1, page, p, 0);
124 * Splice in (1) the interpreter's name for argv[0]
125 * (2) (optional) argument to interpreter
126 * (3) filename of shell script
128 * This is done in reverse order, because of how the
129 * user environment and arguments are stored.
132 * 拼接 (1) argv[0]中放解释程序的名称
133 * (2) (可选的)解释程序的参数
134 * (3) 脚本程序的名称
136 * 这是以逆序进行处理的,是由于用户环境和参数的存放方式造成的。
138 // 复制脚本程序文件名到参数和环境空间中。
p = copy_strings (1, &filename, page, p, 1);
140 // 复制解释程序的参数到参数和环境空间中。
if (i_arg)
p = copy_strings (1, &i_arg, page, p, 2);
147 // 复制解释程序文件名到参数和环境空间中。若出错,则置出错码,跳转到exec_error1。
p = copy_strings (1, &i_name, page, p, 2);
retval = -ENOMEM;
goto exec_error1;
156 * OK, now restart the process with the interpreter's inode.
159 * OK,现在使用解释程序的i 节点重启进程。
161 // 保留原fs 段寄存器(原指向用户数据段),现置其指向内核数据段。
old_fs = get_fs ();
set_fs (get_ds ());
164 // 取解释程序的i 节点,并跳转到restart_interp 处重新处理。
if (!(inode = namei (interp)))
/* get executables inode */
set_fs (old_fs);
retval = -ENOENT;
goto exec_error1;
set_fs (old_fs);
goto restart_
174 // 释放该缓冲区。
brelse (bh);
176 // 下面对执行头信息进行处理。
177 // 对于下列情况,将不执行程序:如果执行文件不是需求页可执行文件(ZMAGIC)、或者代码重定位部分
178 // 长度a_trsize 不等于0、或者数据重定位信息长度不等于0、或者代码段+数据段+堆段长度超过50MB、
179 // 或者i 节点表明的该执行文件长度小于代码段+数据段+符号表长度+执行头部分长度的总和。
if (N_MAGIC (ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
ex.a_text + ex.a_data + ex.a_bss & 0x3000000 ||
inode-&i_size & ex.a_text + ex.a_data + ex.a_syms + N_TXTOFF (ex))
retval = -ENOEXEC;
goto exec_error2;
187 // 如果执行文件执行头部分长度不等于一个内存块大小(1024 字节),也不能执行。转exec_error2。
if (N_TXTOFF (ex) != BLOCK_SIZE)
printk ("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);
retval = -ENOEXEC;
goto exec_error2;
194 // 如果sh_bang 标志没有设置,则复制指定个数的环境变量字符串和参数到参数和环境空间中。
195 // 若sh_bang 标志已经设置,则表明是将运行脚本程序,此时环境变量页面已经复制,无须再复制。
if (!sh_bang)
p = copy_strings (envc, envp, page, p, 0);
p = copy_strings (argc, argv, page, p, 0);
200 // 如果p=0,则表示环境变量与参数空间页面已经被占满,容纳不下了。转至出错处理处。
retval = -ENOMEM;
goto exec_error2;
207 /* OK, This is the point of no return */
208 /* OK,下面开始就没有返回的地方了 */
209 // 如果原程序也是一个执行程序,则释放其i 节点,并让进程executable 字段指向新程序i 节点。
if (current-&executable)
iput (current-&executable);
current-&executable =
213 // 清复位所有信号处理句柄。但对于SIG_IGN 句柄不能复位,因此在322 与323 行之间需添加一条
214 // if 语句:if (current-&sa[I].sa_handler != SIG_IGN)。这是源代码中的一个bug。
for (i = 0; i & 32; i++)
current-&sigaction[i].sa_handler = NULL;
217 // 根据执行时关闭(close_on_exec)文件句柄位图标志,关闭指定的打开文件,并复位该标志。
for (i = 0; i & NR_OPEN; i++)
if ((current-&close_on_exec && i) & 1)
sys_close (i);
current-&close_on_exec = 0;
222 // 根据指定的基地址和限长,释放原来程序代码段和数据段所对应的内存页表指定的内存块及页表本身。
free_page_tables (get_base (current-&ldt[1]), get_limit (0x0f));
free_page_tables (get_base (current-&ldt[2]), get_limit (0x17));
225 // 如果&上次任务使用了协处理器&指向的是当前进程,则将其置空,并复位使用了协处理器的标志。
if (last_task_used_math == current)
last_task_used_math = NULL;
current-&used_math = 0;
229 // 根据a_text 修改局部表中描述符基址和段限长,并将参数和环境空间页面放置在数据段末端。
230 // 执行下面语句之后,p 此时是以数据段起始处为原点的偏移值,仍指向参数和环境空间数据开始处,
231 // 也即转换成为堆栈的指针。
p += change_ldt (ex.a_text, page) - MAX_ARG_PAGES * PAGE_SIZE;
233 // create_tables()在新用户堆栈中创建环境和参数变量指针表,并返回该堆栈指针。
p = (unsigned long) create_tables ((char *) p, argc, envc);
235 // 修改当前进程各字段为新执行程序的信息。令进程代码段尾值字段end_code = a_text;令进程数据
236 // 段尾字段end_data = a_data + a_text;令进程堆结尾字段brk = a_text + a_data + a_bss。
current-&brk = ex.a_bss +
(current-&end_data = ex.a_data + (current-&end_code = ex.a_text));
239 // 设置进程堆栈开始字段为堆栈指针所在的页面,并重新设置进程的用户id 和组id。
current-&start_stack = p & 0xfffff000;
current-&euid = e_
current-&egid = e_
243 // 初始化一页bss 段数据,全为零。
i = ex.a_text + ex.a_
while (i & 0xfff)
put_fs_byte (0, (char *) (i++));
247 // 将原调用系统中断的程序在堆栈上的代码指针替换为指向新执行程序的入口点,并将堆栈指针替换
248 // 为新执行程序的堆栈指针。返回指令将弹出这些堆栈数据并使得CPU 去执行新的执行程序,因此不会
249 // 返回到原调用系统中断的程序中去了。
eip[0] = ex.a_
/* eip, magic happens :-) *//* eip,魔法起作用了 */
/* stack pointer *//* esp,堆栈指针 */
253 exec_error2:
iput (inode);
255 exec_error1:
for (i = 0; i & MAX_ARG_PAGES; i++)
free_page (page[i]);
return (retval);09-1309-0609-0309-13
04-1604-0604-1303-21
◇本站云标签
◇热点推荐怎样把asc函数加进Excel中_百度知道
怎样把asc函数加进Excel中
在函数框中竟没有ASC函数我用的Excel2003, 非常感谢,不知道是什么原因, 那位仁兄能告诉我,怎样把ASC函数加进Excel中去
提问者采纳
数框中列出的只是常用函数以及最近使用过的函数,对话框中“或选择类别”应选择全部,然后去找asc即可,你第一次可以单击fx按钮插入函数
其他类似问题
为您推荐:
其他3条回答
有的,点开函数对话框时,在“函数类别”中选择“文本”,下面第一个就是
正常安装office后就会有所有的函数的,你可以在编辑栏左边的fx处点一下,就会出来函数的框,再在框里输入ASC再点转到就可以找到了,如果还是没办法出来,那肯定是你的office没有安装完整,VB功能没有安装,再装一遍,完全安装一下
在单元格里直接输入&=ASC(code)&
excel的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁

我要回帖

更多关于 execle函数 的文章

 

随机推荐