Errno的比赛条件

时间:2018-06-16 13:19:16

标签: linux multithreading unix parallel-processing operating-system

我们应该如何处理系统的全局变量(例如UNIX中的errno)的竞争条件?我查看了Tanenbaum的现代操作系统(第4版,第117页),并说它使用私有全局变量。所以基本上你为全局变量分配了一些内存块,并将它作为参数传递给每个过程。但是如何解决这个问题呢?

2 个答案:

答案 0 :(得分:0)

嗯,最好的选择是不使用全局变量。编写可重入函数,使用户传递正确类型的变量(通常在C中它将是一个指向变量的指针)并使用它。例如,请参阅strtok_r()

如果它是一个你控制的全局变量,因为它在用户代码中并且由于某种原因你无法避免使用它,那就是thread local storage

如果它是您使用但不能改变的库中的全局,则必须确保使用互斥锁保护它的任何使用。

答案 1 :(得分:0)

正如jww所链接的那样,在大多数多线程感知标准库中,都采取了一些措施来确保系统全局errno在多线程环境中是理智的。在这个时代,一个没有解决这个问题的图书馆必须被考虑在内,而且没有帮助#34;

在多线程库之前的糟糕时期,对errno之类的东西产生副作用的标准库函数的调用必须用信号量保护。 Yeurk。

在现代gcc中,扩展__thread:

__thread long myThreadPrivateLong;

其他编译器可能有类似的东西。我偶尔发现这在我自己的代码中很有用。

当然,stdinstdoutstderr等其他系统全局变量不是线程私有的。这没有任何意义,因为进程只有一个tty(唉*)。在glibc上,采取了一些措施来确保对stdout的多线程访问是半理性的,因为像printf()这样的函数在glibc遇到之后实际输出到stdout之前通过管道进行缓冲。 EOL。结果是两个线程同时调用printf()将使它们的输出行分开。在过去,两次调用printf()所输出的字符只会混杂成一个不可读的混乱。 fprintf(stderr,...)仍然可以获得此功能,因为stderr未被缓冲。

*我说唉,因为如果有特定于线程的stdouts并且终端应用程序每个线程有一个终端选项卡,那将是非常好的。对用户不是很有用,但有时对开发人员非常有用。能够看到单个线程正在做什么是有用的。