我想编写一个模拟串行端口上的设备的程序。我正在尝试使用伪终端来完成此操作。我想要一个不同的进程来控制主人。此过程充当串行设备仿真器。我希望另一个进程(例如 kermit)能够使用从终端与主机通信。由于不同的流程要求,我没有使用任何分叉。互联网上几乎每个伪终端示例都显示了将 fork() 用于主/从。
我让它朝一个方向工作。也就是说,我可以让从属进程将数据写入从属伪终端,而主进程将从主伪终端读取数据就好了。
问题在另一个方向。我无法让主机写入数据和从机读取数据。
我将展示非工作双向代码和工作单向代码。
非工作双向master:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char* argv[])
{
// get the master fd
int masterfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
if(masterfd < 0)
{
perror("getpt");
exit(1);
}
// grant access to the slave
if(grantpt(masterfd) < 0)
{
perror("grantpt");
exit(1);
}
// unlock the slave
if(unlockpt(masterfd) < 0)
{
perror("unlockpt");
exit(1);
}
// get the path to the slave
char slavepath[64];
if(ptsname_r(masterfd, slavepath, sizeof(slavepath)) < 0)
{
perror("ptsname_r");
exit(1);
}
printf("Using %s\n", slavepath);
char bufout = 'D';
char bufin;
int c;
while(1)
{
printf("reading\n");
c = read(masterfd, &bufin, 1);
printf("read %i bytes: %c\n", c, bufin);
if(c == -1) break;
if(bufout == 'D') bufout = 'E';
else if(bufout == 'E') bufout = 'D';
printf("writing %c\n", bufout);
c = write(masterfd, &bufout, 1);
printf("wrote %i bytes\n", c);
if(c == -1) break;
sleep(1);
}
close(masterfd);
return 0;
}
非工作双向奴隶:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
int fd = open("/dev/pts/15", O_RDWR | O_NOCTTY);
if(fd < 0)
{
perror("open");
exit(1);
}
char bufout = 'A';
char bufin;
int c;
while(1)
{
if(bufout == 'A') bufout = 'B';
else if(bufout == 'B') bufout = 'A';
printf("writing %c\n", bufout);
c = write(fd, &bufout, 1);
if(c == -1) break;
printf("reading\n");
c = read(fd, &bufin, 1);
printf("read %i bytes: %c\n", c, bufin);
if(c == -1) break;
sleep(1);
}
close(fd);
}
非工作主机的输出:(注意接收到的第一个字符来自从机,然后是主机写入的字符。换句话说,主机正在读取它写给主机 pts 的相同字符,而忽略从机正在写作,除了第一个字符。)
Using /dev/pts/15
reading
read 1 bytes: B [<--- FROM THE SLAVE]
writing E
wrote 1 bytes
reading
read 1 bytes: E [<--- REST FROM THE MASTER]
writing D
wrote 1 bytes
reading
read 1 bytes: D
writing E
wrote 1 bytes
reading
read 1 bytes: E
writing D
wrote 1 bytes
reading
read 1 bytes: D
^C
非工作从机的输出:(从不接收主机正在写入的内容。)
writing B
reading
^C
工作单向大师:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char* argv[])
{
// get the master fd
int masterfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
if(masterfd < 0)
{
perror("getpt");
exit(1);
}
// grant access to the slave
if(grantpt(masterfd) < 0)
{
perror("grantpt");
exit(1);
}
// unlock the slave
if(unlockpt(masterfd) < 0)
{
perror("unlockpt");
exit(1);
}
// get the path to the slave
char slavepath[64];
if(ptsname_r(masterfd, slavepath, sizeof(slavepath)) < 0)
{
perror("ptsname_r");
exit(1);
}
printf("Using %s\n", slavepath);
char bufout = 'D';
char bufin;
int c;
while(1)
{
printf("reading\n");
c = read(masterfd, &bufin, 1);
printf("read %i bytes: %c\n", c, bufin);
if(c == -1) break;
sleep(1);
}
close(masterfd);
return 0;
}
工作单向奴隶:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
int fd = open("/dev/pts/15", O_RDWR | O_NOCTTY);
if(fd < 0)
{
perror("open");
exit(1);
}
char bufout = 'A';
char bufin;
int c;
while(1)
{
if(bufout == 'A') bufout = 'B';
else if(bufout == 'B') bufout = 'A';
printf("writing %c\n", bufout);
c = write(fd, &bufout, 1);
if(c == -1) break;
sleep(1);
}
close(fd);
}
工作主机的输出:(读取从机成功写入的内容。)
Using /dev/pts/15
reading
read 1 bytes: B
reading
read 1 bytes: A
reading
read 1 bytes: B
reading
read 1 bytes: A
reading
read 1 bytes: B
^C
工作从机的输出:
writing B
writing A
writing B
writing A
writing B
^C