热度 3
2016-5-20 20:55
1022 次阅读|
3 个评论
当要进行多个文件的同时读写时,为了避免等待,有以下方法可以选择: 多进程(提高了复杂性) 多线程(需要同步机制) NONBLOCKING I/O(持续polling消耗了CPU时间) 异步I/O(难以移植,且进程只有拥有一个某类型的信号) IO multiplexing 其中,IO multiplexing是最好的方法。 为了进行IO复用的实验,我使用了一个STM32F103RBT6开发板作为串口设备。 它的功能是,将自身的串口1设置为115200 8N1的波特率,并返回任何接收到的字符串。 字符串以'\r'作为结束: 比如在minicom下通过键盘发送“123456abc\r”,那么就会接收到: R: 123456abc 如果连续键入'\r'(minicom默认以此字符作为Enter键的输入),则有: R: R: R: 在主函数里,将串口进行初始化操作: fd_dev = ::open(DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd_dev 0) { cerr "Error: Cannot open " DEVICE endl; return -1; } termios attr; memset(attr, 0, sizeof(attr)); attr.c_cflag = B115200 | HUPCL | CS8 | CREAD | CLOCAL; attr.c_iflag = IGNPAR; attr.c_cc = 1; if (tcsetattr(fd_dev, TCSANOW, attr) != 0) { cerr "Error: Cannot set termios!" endl; return -1; } 然后重新起一个线程,让它每隔一秒发送一串数据: void *ntid2_print(void *arg) { string str; int count = 0, flag; while (1) { str = "2 Write " + to_string(count++) + "th times." + "\r"; cout "= " str.c_str() endl; flag = ::write(fd_dev, str.c_str(), str.size()); if (flag 0) cerr "Error: Cannot write!" endl; sleep(1); } return ((void *)0); } 执行的结果是: # ./UnixProg_01 = 2 Write 0th times. = 2 Write 1th times. = 2 Write 2th times. = 2 Write 3th times. 这样,串口每隔1s就会收到1个字符串,而标准输入会接收键盘数据。 现在,我需要的功能是,主函数既能够读取串口的数据,也能够读取标准IO的,并将它们都打印到标准输出上。 这里需要使用IO复用的select函数: fd_set rset; char byte; while (1) { FD_ZERO(rset); FD_SET(fd_dev, rset); FD_SET(STDIN_FILENO, rset); select(fd_dev + 1, rset, NULL, NULL, NULL); if (FD_ISSET(fd_dev, rset)) { flag = ::read(fd_dev, byte, 1); if (flag 0) { cerr "Error: Cannot read fd_dev!" endl; return -1; } cout byte flush; } if (FD_ISSET(STDIN_FILENO, rset)) { flag = ::read(STDIN_FILENO, byte, 1); if (flag 0) { cerr "Error: Cannot read fd_dev!" endl; return -1; } cout byte flush; } } 这样,标准输出既会打印串口的数据,又会打印标准输入的内容。 另外,还需要注意的一点是,STDIN_FILENO的FD_SET在循环里面,这是因为: http://stackoverflow.com/questions/7637765/why-fd-set-fd-zero-for-select-inside-of-loop