如果我们在第1步将RFD添加到epoll描述符的时候使用了EPOLLET标志,那么在第5步调用epoll_wait(2)之后将有可能会挂起,因为剩余的数据还存在于文件的输入缓冲区内,而且数据发出端还在等待一个针对已经发出数据的反馈信息。只有在监视的文件句柄上发生了某个事件的时候 ET 工作模式才会汇报事件。因此在第5步的时候,调用者可能会放弃等待仍在存在于文件输入缓冲区内的剩余数据。在上面的例子中,会有一个事件产生在RFD句柄上,因为在第2步执行了一个写操作,然后,事件将会在第3步被销毁。因为第4步的读取操作没有读空文件输入缓冲区内的数据,因此我们在第5步调用 epoll_wait(2)完成后,是否挂起是不确定的。epoll工作在ET模式的时候,必须使用非阻塞套接口,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。最好以下面的方式调用ET模式的epoll接口,在后面会介绍避免可能的缺陷。 i 基于非阻塞文件句柄 ii 只有当read(2)或者write(2)返回EAGAIN时才需要挂起,等待。但这并不是说每次read()时都需要循环读,直到读到产生一个EAGAIN才认为此次事件处理完成,当read()返回的读到的数据长度小于请求的数据长度时,就可以确定此时缓冲中已没有数据了,也就可以认为此事读事件已处理完成。
#include <unistd.h> int execl(const char *pathname,const char *arg, ...); int execlp(const char *filename,const char *arg, ...); int execle(const char *pathname,const char *arg, ... , char *const envp[]); int execv(const char *pathname,char *const argv[]); int execvp(const char *filename,char *const argv[]); int execve(const char *pathname,char *const argv[],char *const envp[]);
函数名中含有字母“ l ”的函数,其参数个数不定。其参数由所谓调用程序的命令行参数列表组成,最后一个NULL表示结束。函数名中含有字母“ v ”的函数,则是使用一个字符串数组指针argv指向参数列表,这一字符串数组和含有“ l ”的函数中的参数列表完全相同,也同样以NULL结束。
函数名中含有字母“ p ”的函数可以自动在环境变量PATH指定的路径中搜索要执行的程序。因此它的第一个参数为filename表示可执行函数的文件名。而其他函数则需要用户在参数列表中指定该程序路径,其第一个参数pathname是路径名。路径的指定可以是绝对路径,也可以是相对路径。但出于对系统安全的考虑,建议使用绝对路径而尽量避免使用相对路径。
函数名中含有字母“ e ”的函数,比其他函数多含有一个参数envp。该参数是字符串数组指针,用于制定环境变量。调用这两个函数时,可以由用户自行设定子进程的环境变量,存放在参数envp所指向的字符串数组中。这个字符串数组也必须由NULL结束。其他函数则是接收当前环境变量。