serial-port - 在Control-C之后还恢复串行端口属性吗?

标签 serial-port posix signals

通过POSIX使用串行端口时,建议先使用tcgetattr()保存原始属性,然后再使用tcsetattr()进行更改,然后在关闭端口之前将其还原。通过按Control-C终止程序或当程序收到SIGINT时该怎么办?我没有在任何系列教程中都看到过这一点。

显然,atexit()函数是不够的,因为默认的SIGINT处理程序不会调用它。因此,似乎必须安装信号处理程序,才能将属性恢复到仍然打开的任何串行端口。从信号处理程序调用tcsetattr()甚至安全吗?

可以简单地认为这个问题无关紧要,但是使用Control-C终止程序是很常见的,尤其是可能花费数十秒才能完成操作的程序。如果在这种情况下不保留串行端口设置是可以的,那么似乎根本没有理由保留它们。如果有的话,最好不要打扰,也不要前后矛盾。

我发现了一些examples of source code doing the above,但是没有充分的文献记载。我想我对这是否是一个好主意的讨论感兴趣。谢谢。

最佳答案

经过进一步的研究,我认为我已经对此表示满意。

首先,在man page for signal中,我注意到特别允许信号处理程序与其他一些信号处理程序一起调用tcsetattr()

信号处理程序例程必须非常小心,因为在其他任意位置中断了其他地方的处理。 POSIX具有“安全功能”的概念。如果信号中断了一个不安全的函数,并且处理程序调用了一个不安全的函数,则该行为是不确定的。在各种标准中明确列出了安全功能。 POSIX.1-2003列表是...`raise()`... signal()`... tcsetattr()`[已剪裁为相关的]

这强烈表明POSIX委员会已经牢记了这种确切的想法,并导致了一种直接的方法:打开序列并保存其属性后,您就更改SIGINT处理程序,然后在处理程序中还原它们并旧的SIGINT处理程序,然后重新引发信号:

static void (*prev_sigint)( int );
static termios saved_attr;
static int fd;

static void cleanup( int ignored )
{
    tcsetattr( fd, TCSANOW, &saved_attr );
    signal( SIGINT, prev_sigint );
    raise( SIGINT );
}

int main( void )
{
    open_serial_and_save_attrs();
    prev_sigint = signal( SIGINT, cleanup );
    ...
}

关于serial-port - 在Control-C之后还恢复串行端口属性吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4009411/

相关文章:

c - 串行设备 : Reading 8N1 works, 但写入单个字节失败

macos - macOS 上的/dev/tty.* 和/dev/cu.* 有什么区别?

python - Bluepy 安装错误

linux - 使用SIGALRM中断open()

c - posix fork() & win32 CreateProcess() 之后的子进程名称是什么?

c++ - 在 Visual Studio 中按下 'Stop Debugging' 按钮时拦截信号/事件

c# - SerialPort UnauthorizedAccessException

linux - 是否可以向属于不同用户的进程发送信号?

c++ - Qt/C++ : QTableView contextmenu and passing through information

c - ljmp 和 setjmp 之间的内存泄漏