我正在尝试使用“ Introduction to Interprocess Communication Using Named Pipes - Full-Duplex Communication Using Named Pipes ”,链接;特别是fd_server.c
(包括在下面以供参考)
这是我的信息和编译行:
:~$ cat /etc/issue Ubuntu 10.04 LTS \n \l :~$ gcc --version gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3 :~$ gcc fd_server.c -o fd_server
fd_server.c
创建两个命名管道,一个用于读取,一个用于写入。可以做的是:在一个终端中,运行服务器并读取(通过cat
)它的写入管道:
:~$ ./fd_server & 2>/dev/null [1] 11354 :~$ 猫 /tmp/np2
在另一个中,写入(使用回声)到服务器的读取管道:
:~$ echo "heeellloooo" > /tmp/np1
回到第一个终端,可以看到:
:~$ 猫 /tmp/np2 嘻嘻嘻 0[1]+ 退出 13 ./fd_server 2> /dev/null
我想做的是进行某种“交互式”(或“壳”式)会话;也就是说,服务器像往常一样运行,但不是运行cat
and echo
,我想使用类似于screen的东西。我的意思是,屏幕可以被称为screen /dev/ttyS0 38400
,然后它进行一种交互式会话,在终端中输入的内容被传递给/dev/ttyS0
,其响应被写入终端。现在,当然,我不能使用screen
,因为在我的情况下,程序有两个独立的节点,据我所知,screen
只能引用一个。
在这种情况下(使用两个单独的读/写管道)如何实现这种“交互式”会话?
下面的代码:
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//#include <fullduplex.h> /* For name of the named-pipe */
#define NP1 "/tmp/np1"
#define NP2 "/tmp/np2"
#define MAX_BUF_SIZE 255
#include <stdlib.h> //exit
#include <string.h> //strlen
int main(int argc, char *argv[])
{
int rdfd, wrfd, ret_val, count, numread;
char buf[MAX_BUF_SIZE];
/* Create the first named - pipe */
ret_val = mkfifo(NP1, 0666);
if ((ret_val == -1) && (errno != EEXIST)) {
perror("Error creating the named pipe");
exit (1);
}
ret_val = mkfifo(NP2, 0666);
if ((ret_val == -1) && (errno != EEXIST)) {
perror("Error creating the named pipe");
exit (1);
}
/* Open the first named pipe for reading */
rdfd = open(NP1, O_RDONLY);
/* Open the second named pipe for writing */
wrfd = open(NP2, O_WRONLY);
/* Read from the first pipe */
numread = read(rdfd, buf, MAX_BUF_SIZE);
buf[numread] = '0';
fprintf(stderr, "Full Duplex Server : Read From the pipe : %sn", buf);
/* Convert to the string to upper case */
count = 0;
while (count < numread) {
buf[count] = toupper(buf[count]);
count++;
}
/*
* Write the converted string back to the second
* pipe
*/
write(wrfd, buf, strlen(buf));
}
编辑:
对,只是为了澄清-似乎我发现了一个讨论非常相似的文档,它是-那里的脚本的修改(“例如,以下脚本配置设备并启动后台进程以复制从串行接收到的所有数据设备到标准输出... ") 用于上述程序如下:
# stty raw #
( ./fd_server 2>/dev/null; )&
bgPidS=$!
( cat < /tmp/np2 ; )&
bgPid=$!
# Read commands from user, send them to device
echo $(kill -0 $bgPidS 2>/dev/null ; echo $?)
while [ "$(kill -0 $bgPidS 2>/dev/null ; echo $?)" -eq "0" ] && read cmd; do
# redirect debug msgs to stderr, as here we're redirected to /tmp/np1
echo "$? - $bgPidS - $bgPid" >&2
echo "$cmd"
echo -e "\nproc: $(kill -0 $bgPidS 2>/dev/null ; echo $?)" >&2
done >/tmp/np1
echo OUT
# Terminate background read process - if they still exist
if [ "$(kill -0 $bgPid 2>/dev/null ; echo $?)" -eq "0" ] ;
then
kill $bgPid
fi
if [ "$(kill -0 $bgPidS 2>/dev/null ; echo $?)" -eq "0" ] ;
then
kill $bgPidS
fi
# stty cooked
因此,将脚本保存为 saystarter.sh
并调用它,会产生以下会话:
$ ./starter.sh
0
i'm typing here and pressing [enter] at end
0 - 13496 - 13497
I'M TYPING HERE AND PRESSING [ENTER] AT END
0~�.N=�(�~� �����}����@������~� [garble]
proc: 0
OUT
这就是我所说的“交互式会话”(忽略调试语句) - 服务器等待我输入命令;它在收到命令后给出输出(在这种情况下,它在第一个命令后退出,启动脚本也是如此)。除此之外,我不想缓冲输入,而是一个字符一个字符地发送(这意味着上面的会话应该在第一次按键后退出,并且只打印一个字母 - 这是我期望stty
raw 会有所帮助的,但是它没有:它只会杀死对两者的反应Enter- Ctrl:) C)
如果已经有一个现有的命令(类似于screen
串行设备,我猜),我只是在徘徊,它将接受两个这样的命名管道作为参数,并通过它们建立一个类似“终端”或“外壳”的会话;或者我是否必须使用上述脚本和/或程序自己的“客户端”,它将充当终端..