150159413 发表于 2012-01-29 17:51

telnet登陆目标板无法接收printf打印信息

CPU : ARM9
BOARD : AT91RM9200

问题描述:
之前使用的是vxworks操作系统,串口和telnet连接目标板都可以接收到打印信息。因项目需求操作系统由vxworks替换为linux,
应用程序起来后,telnet到目标板接收不到printf的打印信息,但是串口可以正常接收。

个人猜测可能是默认输出到串口,因此telnet无法接管这些打印信息。

各位大侠有没有遇到这种情况,如何才可以再打印串口时,打印信息输出到串口,如果telnet连接到目标板,则输出telnet终端呢。
初学linux,多多赐教,多谢!

work4home 发表于 2012-01-31 15:45

这是不可能达到的:
1. 内核的printk把信息打到哪里去呢?这是在内核的命令行参数console=ttyXXX里指定死了,比如console=ttySAC0表示printk的信息输出到串口0
2. telnet上去之后,printf的输出信息是输出到一个“虚拟的终端”去的,你可以用ps命令看一下这个telnet对应的/bin/sh进程ID,ls/proc/进程ID/fd -l 就可以知道这个虚拟的终端对应什么文件。
你可以看到0、1、2这3个文件都是对应一个“临时生成的虚拟的文件”
3. 所以,内核的信息不可能在telnet界面显示出来,你想看的话,可以为dmesg命令查看

150159413 发表于 2012-01-31 17:18

回复 2# work4home

谢谢答复。


发现一点细节:
如果在文件系统起来后,telnet到目标板(此时是启动一个sh的,有一个PID,如果虚拟终端是/dev/pts/0),然后手动启动应用程序,应用程序的打印信息是可以接收到的。
但是关闭掉这次连接的终端后,再次telnet到目标板,就无法收到应用程序的打印信息,因为此时是又启动了一个sh,PID也跟上次的不一样了,最主要的是虚拟终端为/dev/pts/1。

意思就是不管你关闭多少次,再telnet到目标板,原来可以接收消息的虚拟终端/dev/pts/0一直分配不到,但是其他的终端,如/dev/pts/1就可以再次使用。

现在疑惑的是,这个打印信息是与首次分配的PID有关,还是与虚拟终端设备号有关。
也在考虑是不是与busybox里的telnet代码相关。也在考虑是不是需要在那里加重定向输出的代码或者脚本。

如果不能实现telnet接管打印信息的话,那么对于linux产品问题定位很不方便,100个产品的随机问题不可能找100个PC,使用100个串口都接上吧。

我也尝试了dmesg,但是只打印了内核启动的信息,应用程序的打印信息不存在。
谢谢work4home,还请多多交流。


   

work4home 发表于 2012-01-31 17:38

每次telnet上去,就会生成一个/dev/pts/x文件,每次都不会相同的;
你telnet上去后,会有一个/bin/sh,在这个/bin/sh里启动应用程序,那么这个/bin/sh就是这个应用程序的父进程;当你把这个telne连接关闭后,/bin/sh会退出,它的子进程也会退出。
所以你说的“再次telnet到目标板,就无法收到应用程序的打印信息”,原因是这个应用程序早就死掉了。


应用程序的打印信息,与它的父进程的0、1、2三个文件相关。在telnet界面,这3个文件对应虚拟的设备。
根据这个原理,你可以在应用程序里close(0),close(1),close(2),然后再打开3个文件,这样printf就可以输出到这些文件去了。
通常的做法是:不直接用printf,而是自己实现打印,打到文件去、或是发到服务器去。

150159413 发表于 2012-02-01 10:16

回复 4# work4home


首先谢谢work4home兄弟的交流。

根据work4home兄弟的说话,本人有个想法,应该是可以实现telnet接管打印信息,还请work4home给点意见。
这个打印信息的函数不能使用printf,应该自己实现一个打印函数,把输出信息重定向到新生成的虚拟终端pts上。当遍历终端时没有发现有虚拟终端,或者此终端退出时,需要重定向到console。

原本有想法,自己参考busybox代码实现telnet服务器,这个工作量还是比较大的,暂时放弃。另外监听socket连接,输出重定向到sock句柄,也不可行,无法区分其他类型的tcp连接。

因此起一个线程来做重定向的事,应该是易行的一个方法。只是目前还不知道有没有什么系统函数可以使用,目前想到一种笨的查找方法。先查找进程PID,再由进程PID去/proc/PID/fd 查找终端,再做重定向工作。

150159413 发表于 2012-02-01 10:25

work4home 发表于 2012-01-31 17:38 static/image/common/back.gif
每次telnet上去,就会生成一个/dev/pts/x文件,每次都不会相同的;
你telnet上去后,会有一个/bin/sh,在这 ...


纠正work4home兄弟一句话。“每次telnet上去,就会生成一个/dev/pts/x文件,每次都不会相同的”
这个是可以相同的,不同的进程ID。请看下面:
# ps
353 root      1696 R    -sh-------这个是telnet的进程ID
372 root      1684 R    ps
# ls /proc/353/fd -l
lrwx------    1 root   root         64 Jan1 00:28 0 -> /dev/pts/0
lrwx------    1 root   root         64 Jan1 00:29 1 -> /dev/pts/0
lrwx------    1 root   root         64 Jan1 00:29 10 -> /dev/tty
lrwx------    1 root   root         64 Jan1 00:29 2 -> /dev/pts/0
#
然后我关闭后,再次telnet到目标板:
# ps
374 root      1692 S    -sh
375 root      1684 R    ps
# ls /proc/374/fd -l
lrwx------    1 root   root         64 Jan1 17:51 0 -> /dev/pts/0
lrwx------    1 root   root         64 Jan1 17:51 1 -> /dev/pts/0
lrwx------    1 root   root         64 Jan1 17:51 10 -> /dev/tty
lrwx------    1 root   root         64 Jan1 17:51 2 -> /dev/pts/0
#

150159413 发表于 2012-02-03 18:23

这个问题已经解决了
需要写点代码就可以实现。
下次再贴方法,下班回家了

150159413 发表于 2012-02-07 09:42

需要在接管打印的进程内,做一个线程,目的是接收需要打印的虚拟设备。
比如现在是在/dev/console 打印信息的,此时我们telnet到目标板,tty看到设备名/dev/pst/0,我们需要把原来的打印信息console被pst/0接管。

主进程做一个服务端的代码,监听某个端口,当客户端有接入时,接收客户端消息,主要使用dup2来实现输出的重映射功能。

客户端代码主要是连接服务器,发送虚拟终端设备名。

思路就是这样了

linux_xxxx 发表于 2012-02-23 10:38

回复 8# 150159413


    能附上代码吗,我也正做相似功能
   万分感激~~

killdog1982 发表于 2012-03-10 12:45

没想到还有人跟我碰到一样的问题哈,mark一下,慢慢看。
我就自己重写一个函数定向到文件,然后cat一下好了。
不过我发现普通函数printf telnet是能显示的,但是线程里的printf竟然不显示,我晕死。
页: [1] 2
查看完整版本: telnet登陆目标板无法接收printf打印信息