Linux Shell 的小问题 (高分请教达人)

threeleafzerg007 2009-08-04 04:46:12
代码逻辑是:自己先pipe建立管道 然后fork一个子进程 把子进程的输入输出重定向到 pipe2端 然后就 execl("/bin/sh" "sh" (char*)0) 最后主进程通过获取自己的输入 然后通过管道传至子进程 子进程因为是bash 然后执行命令 把结果通过 通过管道返回给 主进程

遗憾的是只有第一次执行命令是正确的 然后就一直显示所输入的东西 并且第一次输入时间如果很长 它依然会显示所输入的东西 原因何在,请教高手?


#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/select.h>
#include <errno.h>


int fds[2];

void do_shell();
void do_ioredirect();
void sig_chld(int signo)
{
printf("receive a SIGCHLD\n");
return;
}

int main(int argc,char **argv)
{
char buf[256];
int maxfd,nread;

signal(SIGCHLD,sig_chld);

if(pipe(fds) < 0)
{
perror("pipe");
exit(-1);
}

do_shell();

for(;;)
{
fd_set rset;
FD_ZERO(&rset);
FD_SET(0,&rset);
FD_SET(fds[0],&rset);
maxfd = fds[0] + 1;
memset(buf,0x00,sizeof(buf));

int n = select(maxfd,&rset,NULL,NULL,NULL);
if( -1 == n && errno == EINTR)
continue;
else if(-1 == n)
{
perror("select");
exit(-1);
}
if(FD_ISSET(0,&rset))
{
nread = read(0,buf,256);
write(fds[1],buf,nread);
}
if(FD_ISSET(fds[0],&rset))
{
nread = read(fds[0],buf,256);
printf("%s",buf);
}

}
return 0;
}

void do_shell()
{
int pid;

switch((pid = fork()))
{
case -1:
perror("fork");
exit(-1) ;
case 0:
do_ioredirect();
if(execl("/bin/bash","sh",(char *)0) < 0)
{
perror("execl");
exit(-1);
}
default:
break;
}
return;
}

void do_ioredirect()
{
if(dup2(fds[0],STDIN_FILENO) < 0)
{
perror("fd[0] dup2");
exit(-1);
}

if(dup2(fds[1],STDOUT_FILENO) < 0)
{
perror("fd[1] dup2");
exit(-1);
}
}


...全文
247 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
threeleafzerg007 2009-08-05
  • 打赏
  • 举报
回复
我已经找到原因了 呵呵 因为 /bin/sh 执行的时候用了 -i 所以即使被重定向依然会 读终端 所以会有信号

system 肯定是不行的了 popen还靠点谱 但是为了每次执行一个shell 命令而 起一个进程 关一个进程 代价实在太大了!
steptodream 2009-08-05
  • 打赏
  • 举报
回复
友情UP!
sunnyqboy 2009-08-04
  • 打赏
  • 举报
回复
用system直接执行结果,传给进程不行么?楼主使用父子进程传值,是为了增加并行性?
blackbillow 2009-08-04
  • 打赏
  • 举报
回复
On POSIX-compliant platforms, SIGTTIN is the signal sent to a process when it attempts to read from the tty while in the background.
threeleafzerg007 2009-08-04
  • 打赏
  • 举报
回复
在我写了如下代码

void sig_ttin(int signo)
{
printf("receive a SIGTTIN");
return ;
}

signal(SIGTTIN,sig_ttin);

终端就不停的打印出 sig_ttin的字符串,显然我的主进程不断的收到SIGTTIN 想问一下这是为何?有没有人能解释哈?
threeleafzerg007 2009-08-04
  • 打赏
  • 举报
回复
另一种ps

charlesye@charlesye-desktop:~/Program/salira_shell$ ps -ely | grep test
T 1000 5917 5266 0 80 0 720 696 signal pts/0 00:00:00 test
T 1000 6054 5266 0 80 0 724 696 signal pts/0 00:00:00 test

应该是被信号停止了, 想问一下是何种信号(明天我会写代码捕捉) 为何会产生信号?
threeleafzerg007 2009-08-04
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 blackbillow 的回复:]
管道应该是单向的,但这里你拿来双向传输数据会出问题的
[/Quote]

你说到点子上了

修改代码如下:

#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/select.h>
#include <errno.h>


int fds1[2];
int fds2[2];

void do_shell();
void do_ioredirect();
void sig_chld(int signo)
{
printf("receive a SIGCHLD\n");
return;
}

int main(int argc,char **argv)
{
char buf[256];
int maxfd,nread;

signal(SIGCHLD,sig_chld);

if(pipe(fds1) < 0)
{
perror("pipe");
exit(-1);
}

if(pipe(fds2) < 0)
{
perror("pipe");
exit(-1);
}


do_shell();
for(;;)
{
fd_set rset;
FD_ZERO(&rset);
FD_SET(0,&rset);
FD_SET(fds2[0],&rset);
maxfd = fds2[0] + 1;
memset(buf,0x00,sizeof(buf));

int n = select(maxfd,&rset,NULL,NULL,NULL);
if( -1 == n && errno == EINTR)
continue;
else if(-1 == n)
{
perror("select");
exit(-1);
}
if(FD_ISSET(0,&rset))
{
nread = read(0,buf,256);
write(fds1[1],buf,nread);
}
if(FD_ISSET(fds2[0],&rset))
{
nread = read(fds2[0],buf,256);
printf("%s",buf);
}

}
return 0;
}

void do_shell()
{
int pid;

switch((pid = fork()))
{
case -1:
perror("fork");
exit(-1) ;
case 0:
do_ioredirect();
if(execl("/bin/sh","/bin/sh","-i",(char *)0) < 0)
{
perror("execl");
exit(-1);
}
default:
close(fds1[0]);
close(fds2[1]);
break;
}
return;
}

void do_ioredirect()
{

if(dup2(fds1[0],STDIN_FILENO) < 0)
{
perror("fd[0] dup2");
exit(-1);
}

if(dup2(fds2[1],STDOUT_FILENO) < 0)
{
perror("fd[1] dup2");
exit(-1);
}
close(fds1[1]);
close(fds2[0]);
}



基本工作正常 不过出现新问题:

进程在执行几个命令后会发生:

charlesye@charlesye-desktop:~/Program/salira_shell$ ./test
$ who
charlesye tty7 Aug 4 19:46 (:0)
charlesye pts/0 Aug 4 19:46 (192.168.108.1)
$ ls

[3]+ Stopped ./test



进程状态是:


charlesye@charlesye-desktop:~/Program/salira_shell$ ps aux | grep test
1000 5626 0.0 0.1 2784 724 pts/0 T 20:01 0:00 ./test
1000 5648 0.0 0.1 2784 724 pts/0 T 20:08 0:00 ./test
1000 5682 0.0 0.1 2784 724 pts/0 T 20:09 0:00 ./test
1000 5691 0.0 0.1 2020 568 pts/0 S+ 20:10 0:00 grep test



有人知道为啥它会被停止不?
yhf365 2009-08-04
  • 打赏
  • 举报
回复
进来学习一下
blackbillow 2009-08-04
  • 打赏
  • 举报
回复
void do_ioredirect()
{
if(dup2(fds[0],STDIN_FILENO) < 0)
{
perror("fd[0] dup2");
exit(-1);
}
/* 注释掉这一段就没问题了
if(dup2(fds[1],STDOUT_FILENO) < 0)
{
perror("fd[1] dup2");
exit(-1);
}
*/
}
blackbillow 2009-08-04
  • 打赏
  • 举报
回复
管道应该是单向的,但这里你拿来双向传输数据会出问题的
ShowMan 2009-08-04
  • 打赏
  • 举报
回复
兄弟技术挺好,写的不错,mark一下。
晚上好好看看。
Jagen在路上 2009-08-04
  • 打赏
  • 举报
回复
你的shell脚本怎么写的?
内容概要:本文系统研究了开关频率大于谐振频率(fs>fr)工况下,移相混合控制LLC谐振变换器在低压增益区域的工作特性,深入分析其在变频与移相结合控制模式下的调制机理、工作模态划分及损耗分布规律。通过Simulink平台构建高保真仿真模型,对变换器在不同负载和输入条件下的电压增益、转换效率、关键器件电压电流应力等性能指标进行了全面仿真验证,重点探讨了其在低增益区间的软开关实现能力与效率优化潜力,旨在提升LLC变换器在宽范围输入输出应用中的动态响应与能源转换效率。; 适合人群:从事电力电子变换器设计、高频电源开发及相关领域的高校研究生、科研院所研究人员及企业研发工程师,要求具备扎实的电路理论基础、电力电子技术知识以及一定的Simulink仿真能力。; 使用场景及目标:①深入理解LLC谐振变换器在fs>fr条件下采用移相混合控制的内在工作机理与模态转换过程;②掌握利用Simulink搭建复杂谐振变换器精确仿真模型的方法与技巧;③分析并优化低压增益区的增益特性与损耗构成,为设计高效率、高功率密度的软开关电源提供理论依据和数据支持; 阅读建议:建议读者结合文中所述仿真模型,亲自复现仿真过程,重点观察不同控制参数(如移相比、开关频率)对电压增益曲线和关键波形的影响,并对比传统变频控制策略,深入探究混合控制在拓宽调压范围、提升轻载效率方面的优势,从而深化对现代高效谐振电源设计的理解。
内容概要:本文提出了一种基于粒子群优化算法(PSO)的配电网光伏储能双层优化配置模型,以IEEE33节点系统为标准算例,实现光伏发电单元与储能系统的协同选址与定容优化。该模型采用双层架构设计,上层以投资成本、运行经济性及网络损耗最小为目标优化设备配置方案,下层通过潮流计算评估系统在不同负荷场景下的运行性能,综合考虑电压稳定性、供电可靠性及可再生能源消纳能力,最终通过Matlab编程实现完整求解流程,为高渗透率分布式电源接入背景下的配电网规划提供了有效的技术支撑。; 适合人群:具备电力系统分析基础和Matlab编程能力的研究生、高校科研人员及从事新能源并网、智能配电网规划与优化的工程技术人员。; 使用场景及目标:①研究含高比例光伏接入的配电网规划与运行协同优化问题;②掌握双层优化建模方法与粒子群算法在复杂电力系统问题中的应用技巧;③为实际工程中分布式光伏与储能系统的科学选址与容量配置提供理论依据与仿真验证平台。; 阅读建议:建议读者结合Matlab代码深入理解双层迭代求解机制,重点关注算法收敛性分析、参数敏感性测试,并可通过更换初始种群、调整权重因子或引入其他标准测试系统(如IEEE69节点)进行对比实验,进一步验证所提模型的普适性与鲁棒性。

23,223

社区成员

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

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