概述
为什么要自己实现一个popenpclose函数功能呢?因为,有时系统popen打开的文件,有时会出现pclose时一直阻塞着,导致整个应用程序无法正常结束,此时使用我们自己实现的popen,则可以获得进程ID,然后通过kill该进程ID来结束popen开启的文件;
FILE* Popen(const char* commandstr, const char* mode)
{
pid_t pid;
int pfd[2];
int nRet = pipe(pfd); // 创建管道(pfd[0] 读管道,pfd[1] 写管道)
if (-1 == nRet)
{
printf("error: pipe() call failsn");
WriteLog(LOG_INFO, "[LogFileMonitor] error: pipe() call fails");
return NULL;
}
pid = fork();
if (pid < 0)
{
printf("error: fork() call fails.n");
WriteLog(LOG_INFO, "[LogFileMonitor] error: fork() call fails");
return NULL;
}
else if (pid == 0)
{
printf("I am child process, pid = %dn", getpid());
WriteLog(LOG_INFO, "[LogFileMonitor] I am child process, pid = %d", getpid());
// 负责写数据 --- 写管道
close(pfd[0]);
if (pfd[1] != STDOUT_FILENO)
{
dup2(pfd[1], STDOUT_FILENO); // 标准输出 指向 管道的输出文件描述符
close(pfd[1]);
}
execl(SHELL, "sh", "-c", commandstr, (char *)0);
_exit(127);
}
else
{
printf("I am parent process, pid = %dn", getpid());
WriteLog(LOG_INFO, "[LogFileMonitor] I am parent process, pid = %d", getpid());
// 负责读数据 --- 读管道
close(pfd[1]);
FILE *fp = NULL;
if ((fp = fdopen(pfd[0], "r")) == NULL)
{
return NULL;
}
return fp;
}
}
int Pclose(FILE* fp)
{
//使用非阻塞io
int flags = 0;
int nfd = fileno(fp);
if (flags = fcntl(nfd, F_GETFL, 0) < 0)
{
LOG(LERROR) << "fcntl() get failed";
WriteLog(LOG_ERROR, "[LogFileMonitor] fcntl() get failed");
return false;
}
flags &= ~O_NONBLOCK;
if (fcntl(nfd, F_SETFL, flags) < 0)
{
LOG(LERROR) << "fcntl() set noblock failed";
WriteLog(LOG_ERROR, "[LogFileMonitor] set noblock failed");
return false;
}
if (fclose(fp) == EOF)
{
return -1;
}
WriteLog(LOG_INFO, "[LogFileMonitor] Pclose() _exit(128)");
_exit(128);
return 0;
}
最后
以上就是飘逸砖头为你收集整理的使用fork(), pipe() 实现linux的popen, pclose功能的全部内容,希望文章能够帮你解决使用fork(), pipe() 实现linux的popen, pclose功能所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复