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);
}
}


...全文
259 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脚本怎么写的?
内容概要:本文详细描述了机械零件Part4的设计与建模过程,重点围绕三维建模中的几何构造操作展开。首先基于原零件三视图确定关键尺寸,依次创建多个同心圆柱体结构,包括外层圆柱体(52、52、5)、中间圆柱体(25、25、7)以及中心孔结构(16、16、12)。随后对底部圆柱体进行临时加高处理,以便在顶面草绘中构建辅助图形:以计算得出的半径17.5画圆,并在其接触面上方绘制半径为3的小圆,进而引出两条分别成60°和-60°的斜线,配合一条水平线形成三角形轮廓。接着在其余两角复制相同的小圆结构,清理多余线条后完成草图设计。利用该草图执行“拉伸切除”操作,深度设为16.28mm,实现特征开槽。最后将底部圆柱体恢复原始高度5mm,完成整体结构修改。; 适合人群:具备基础CAD建模能力的机械设计人员或工科类学生;熟悉SolidWorks、AutoCAD等三维设计软件的操作者;从事零部件逆向设计或结构优化的技术人员。; 使用场景及目标:①用于学习复杂零件的分步建模方法,掌握从三视图到三维实体的转换技巧;②理解拉伸、切除、草图约束、包围盒设置等核心建模命令的实际应用;③提升对尺寸链计算、辅助线构建及几何关系控制的理解与实践能力。; 阅读建议:建议结合文中参数逐步在建模软件中复现操作,重点关注草图绘制逻辑与切除特征的关联性,注意各步骤间的顺序依赖关系,避免因尺寸或约束错误导致建模失败。
内容概要:本文系统阐述了基于格子Boltzmann方法(Lattice Boltzmann Method, LBM)对二维通道内多孔介质流动进行数值模拟的理论体系、Matlab代码实现流程及结果验证方法。深入剖析了LBM在处理复杂流体系统尤其是不规则几何结构多孔介质流动中的独特优势,详细介绍了模型构建过程、边界条件设定、碰撞与传播环节的算法实现机制,并通过Matlab编程完成仿真运算,实现了对速度场、压力场等关键物理量的可视化分析与精度验证,确保模拟结果具备良好的准确性与可靠性。; 适合人群:具备流体力学基础知识和一定Matlab编程能力的研究生、科研人员及工程技术人员,尤其适合从事多孔介质流动、计算流体力学(CFD)或LBM方法研究的相关领域研究人员。; 使用场景及目标:①掌握格子Boltzmann方法的核心原理及其在多孔介质流动模拟中的具体应用;②学习利用Matlab实现LBM算法并开展科学计算与结果可视化的方法;③为相关科研项目、学术论文复现或实际工程仿真提供可复用的代码框架与技术实施路径。; 阅读建议:建议读者结合流体力学与数值计算相关背景知识,逐步理解算法推导过程,动手运行并调试所提供的Matlab代码,通过调整参数或几何模型加深对LBM方法灵活性与适用性的认识,同时鼓励将该方法拓展至三维流动或多物理场耦合问题的研究中。

23,224

社区成员

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

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