Я пытаюсь работать с " Введение в межпроцессное взаимодействие с использованием именованных каналов - полнодуплексное взаимодействие с использованием именованных каналов ", link ; в частности 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
:~$ cat /tmp/np2
и в другом случае записать (используя echo) в канал чтения сервера:
:~$ echo "heeellloooo" > /tmp/np1
возвращаясь к первому терминалу, можно увидеть:
:~$ cat /tmp/np2
HEEELLLOOOO
0[1]+ Exit 13 ./fd_server 2> /dev/null
То, что я хотел бы сделать, это сделать своего рода «интерактивный» (или «подобный оболочке») сеанс; то есть сервер работает как обычно, но вместо cat
и 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));
}
Edit:
Правильно, просто для пояснения - кажется, я нашел документ , где обсуждается нечто очень похожее, это - модификация скрипта там (" Например, следующий скрипт конфигурирует устройство и запускает фоновый процесс для копирования всех полученных данных с последовательного устройства на стандартный вывод ...") для указанной выше программы:
# 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
Итак, сохранение сценария, как, скажем, starter.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
в отношении последовательных устройств, я думаю), которая приняла бы два таких именованных канала в качестве аргументов и установила бы "терминал" или "оболочку", как сессия через них; или мне придется использовать сценарии, как указано выше, и / или запрограммировать собственный «клиент», который будет вести себя как терминал.