Ste*_*dis 9 sockets linux arm fork exec
我正在开发一个包含多个服务器套接字的应用程序,每个服务器套接字都运行在一个独特的线程
其中一个线程调用外部实用程序(脚本).此脚本调用将消息发送到其中一个服务器套接字的实用程序(客户端).
最初,我system()
用来执行这个外部脚本,但我们无法使用它,因为我们必须确保服务器套接字在分叉执行外部脚本的子代中关闭.
我现在请fork()
和execvp()
我自己.我fork()
然后在孩子中关闭所有服务器套接字然后调用execvp()
以执行脚本.
现在,所有这一切都很好.问题是脚本有时会向服务器应用程序报告错误.该脚本通过调用另一个打开TCP套接字并发送相应数据的应用程序(客户端)来发送这些错误.我的问题是客户端应用程序获取系统调用0
返回的值socket()
.
注意:仅当使用我的forkExec()函数调用脚本/客户端应用程序时才会发生此问题.如果手动socket()
调用脚本/客户端应用程序,则调用会正常执行,并且工作正常.
基于这些信息,我怀疑它是我的fork()execvp()代码中的一些东西......有什么想法吗?
void forkExec()
{
int stat;
stat = fork();
if (stat < 0)
{
printf("Error forking child: %s", strerror(errno));
}
else if (stat == 0)
{
char *progArgs[3];
/*
* First, close the file descriptors that the child
* shouldn't keep open
*/
close(ServerFd);
close(XMLSocket);
close(ClientFd);
close(EventSocket);
close(monitorSocket);
/* build the arguments for script */
progArgs[0] = calloc(1, strlen("/path_to_script")+1);
strcpy(progArgs[0], "/path_to_script");
progArgs[1] = calloc(1, strlen(arg)+1);
strcpy(progArgs[1], arg);
progArgs[2] = NULL; /* Array of args must be NULL terminated for execvp() */
/* launch the script */
stat = execvp(progArgs[0], progArgs);
if (stat != 0)
{
printf("Error executing script: '%s' '%s' : %s", progArgs[0], progArgs[1], strerror(errno));
}
free(progArgs[0]);
free(progArgs[1]);
exit(0);
}
return;
}
Run Code Online (Sandbox Code Playgroud)
客户端应用代码:
static int connectToServer(void)
{
int socketFD = 0;
int status;
struct sockaddr_in address;
struct hostent* hostAddr = gethostbyname("localhost");
socketFD = socket(PF_INET, SOCK_STREAM, 0);
Run Code Online (Sandbox Code Playgroud)
上面的调用返回0.
if (socketFD < 0)
{
fprintf(stderr, "%s-%d: Failed to create socket: %s",
__func__, __LINE__, strerror(errno));
return (-1);
}
memset(&address, 0, sizeof(struct sockaddr));
address.sin_family = AF_INET;
memcpy(&(address.sin_addr.s_addr), hostAddr->h_addr, hostAddr->h_length);
address.sin_port = htons(POLLING_SERVER_PORT);
status = connect(socketFD, (struct sockaddr *)&address, sizeof(address));
if (status < 0)
{
if (errno != ECONNREFUSED)
{
fprintf(stderr, "%s-%d: Failed to connect to server socket: %s",
__func__, __LINE__, strerror(errno));
}
else
{
fprintf(stderr, "%s-%d: Server not yet available...%s",
__func__, __LINE__, strerror(errno));
close(socketFD);
socketFD = 0;
}
}
return socketFD;
}
Run Code Online (Sandbox Code Playgroud)
仅供参考
操作系统:Linux
Arch:ARM32
内核:2.6.26
R S*_*hko 12
socket()在出错时返回-1.
返回0表示socket()成功并为您提供文件描述符0.我怀疑您关闭的文件描述符之一具有文件描述符0,一旦关闭,下一次调用分配文件描述符的函数将返回fd 0因为它可用.
值为0的套接字很好,这意味着stdin已关闭,这将使fd 0可供重用 - 例如通过套接字.
机会是你在forkExec()子路径(XMLSocket/ServerFd)等中关闭的文件描述符之一.)fd 0.这将启动fd 0关闭的子项,当您从命令行运行应用程序时不会发生这种情况,因为fd 0将作为shell的stdin打开.
如果您希望套接字不是0,1或2(stdin/out/err),请在所有close()调用之后在forkExec()函数中调用以下内容
void reserve_tty()
{
int fd;
for(fd=0; fd < 3; fd++)
int nfd;
nfd = open("/dev/null", O_RDWR);
if(nfd<0) /* We're screwed. */
continue;
if(nfd==fd)
continue;
dup2(nfd, fd);
if(nfd > 2)
close(nfd);
}
Run Code Online (Sandbox Code Playgroud)
检查套接字返回-1表示发生错误.