我正在读一本名为Linux System Programming的书。 引用本书:
那么系统调用和其他库函数呢? 如果您的进程正在写入文件或分配内存,并且信号处理程序写入同一文件或调用malloc(),该怎么办? 有些function显然不可重入。 如果一个程序正在执行一个非重入函数并且发生信号并且信号处理程序然后调用相同的非重合函数,则可能发生混乱。
但接下来会:
保证重入函数
保证可以安全重入的function用于信号
一些function在这里..
写()
一些function在这里..
我很困惑,是write()
可重入,还是不可以? 因为我认为它与声明冲突:
如果您的进程正在写入文件,该怎么办?
只是为了补充@Joachim Pileborg先生在他的回答中提到的内容,根据Reentrancy的wiki条目,函数可重入的基本规则是
详细说明,该函数(如果是可重入的)不会对其自身的实现 (引入它自己使用的内部数据结构)产生任何问题,无论是从不同的上下文调用。
提供给函数的参数(例如文件描述符)不会影响它的重入。
因此,对于write()
,函数本身是Reentrant,但如果从不同的线程调用相同的文件描述符,则显然会产生错误的结果。 同样,这并不意味着, write()
的可重入性消失了。 它是可重入的 ,但不是线程安全的,这两个是不同的方面。
如果你可以从不同的上下文调用一个函数而不打扰来自另一个上下文的另一个调用,则可重入更多。
以strtok
函数为例。 它通常包含一个static
局部变量,用于跟踪您要标记的字符串中的下一个位置。 由于本地static
变量在函数的所有调用之间共享,因此从两个不同的上下文调用函数将导致问题。
另一方面, write
系统调用没有它在调用之间存储的内部数据,这使得从不同的上下文调用是安全的。
重要的是要注意重入与线程安全不同。 以write
函数为例,因为它是可重入的,你可以使用不同的文件从不同的线程调用它,而不必担心内部数据会被破坏。 但是,它不是线程安全的。 使用相同的文件描述符从不同的线程调用它将导致问题。
您引用的文档是指信号处理程序 。 这是一种非常特殊的function类型,在特殊情况下调用,并被视为特定的系统编程。 他们无视程序中的正常控制流程。
如果您不是在编写信号处理程序,那么这些文档并不适用于您。 不过,这是Mac OS上信号安全的function列表:
$ man sigaction The following functions are either reentrant or not interruptible by signals and are async-signal safe. Therefore applications may invoke them, without restriction, from signal-catching functions: Base Interfaces: _exit(), access(), alarm(), cfgetispeed(), cfgetospeed(), cfsetispeed(), cfsetospeed(), chdir(), chmod(), chown(), close(), creat(), dup(), dup2(), execle(), execve(), fcntl(), fork(), fpathconf(), fstat(), fsync(), getegid(), geteuid(), getgid(), getgroups(), getpgrp(), getpid(), getppid(), getuid(), kill(), link(), lseek(), mkdir(), mkfifo(), open(), pathconf(), pause(), pipe(), raise(), read(), rename(), rmdir(), setgid(), setpgid(), setsid(), setuid(), sigaction(), sigaddset(), sigdelset(), sigemptyset(), sigfillset(), sigismember(), signal(), sigpending(), sigprocmask(), sigsuspend(), sleep(), stat(), sysconf(), tcdrain(), tcflow(), tcflush(), tcgetattr(), tcgetpgrp(), tcsendbreak(), tcsetattr(), tcsetpgrp(), time(), times(), umask(), uname(), unlink(), utime(), wait(), waitpid(), write().
关于write
线程安全性,Sourav Ghosh和Joachim Pileborg的答案似乎不正确:
write
应该是根据POSIX.1-2008的线程安全的,因为它不在此列表中 。
但是,来自glibc wiki :
目前Linux写入系统调用不是MT安全的。 竞争写入的多个线程可能获得相同的文件位置值并写入相同的位置,从而导致数据丢失。
似乎这个问题已在Linux内核中修复(参见linux内核邮件列表 )。
以上就是c/c++开发分享C中的重入和重入?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/545892.html