C11 相当于 POSIX flockfile()?

C11 equivalent of POSIX flockfile()?

POSIX 和 C11 都要求流具有关联的锁以防止数据竞争和交错。 POSIX 文档 flockfile() 和相关函数以允许线程安全 I/O 跨越多个调用。是否有等效的 C 函数?我不记得一个,也没有找到一个被提到的,这并不一定意味着一个不存在。

在相关说明中,假设任何声称 POSIX 一致性的实现在使用 C11 threads.h 时都会尊重 flockfile() 是否安全?我认为大多数支持 threads.h 的主要 POSIX 兼容 C 实现都是通过构建 pthreads 来实现的,这意味着这种假设通常是安全的。但是,多线程很难,了解异常情况会很有帮助。

Windows Stockfish 中的实现:

void flockfile(FILE *F)
{
  if ((F >= (&__iob_func()[0])) && (F <= (&__iob_func()[_IOB_ENTRIES-1]))) {
    _lock(_STREAM_LOCKS + (int)(F - (&__iob_func()[0])));
    F->_flag |= _IOLOCKED;
  } else
    EnterCriticalSection(&(((_FILEX *)F)->lock));
}

void funlockfile(FILE *F)
{
  if ((F >= (&__iob_func()[0])) && (F <= (&__iob_func()[_IOB_ENTRIES-1]))) {
    F->_flag &= ~_IOLOCKED;
    _unlock(_STREAM_LOCKS + (int)(F - (&__iob_func()[0])));
  } else
    LeaveCriticalSection(&(((_FILEX *)F)->lock));
}

https://github.com/syzygy1/Cfish/blob/5dbf00f9ffae28b0c96a713e897d718204af73e9/src/misc.c#L299

或者Android它是如何工作的:

void
flockfile(FILE * fp)
{
    LockTable*  t = lock_table_lock();
    if (t != NULL) {
        FileLock**  lookup = lock_table_lookup(t, fp);
        FileLock*   lock   = *lookup;
        if (lock == NULL) {
            pthread_mutexattr_t  attr;
            /* create a new node in the hash table */
            lock = malloc(sizeof(*lock));
            if (lock == NULL) {
                lock_table_unlock(t);
                return;
            }
            lock->next        = NULL;
            lock->file        = fp;
            pthread_mutexattr_init(&attr);
            pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
            pthread_mutex_init( &lock->mutex, &attr );
            *lookup           = lock;
        }
        lock_table_unlock(t);
        /* we assume that another thread didn't destroy 'lock'
        * by calling fclose() on the FILE*. This can happen if
        * the client is *really* buggy, but we don't care about
        * such code here.
        */
        pthread_mutex_lock(&lock->mutex);
    }
}

https://source.codeaurora.org/external/gigabyte/qrd-gb-ssss-7225/plain/android/bionic/libc/stdio/flockfile.c

Both POSIX and C11 require that streams have an associated lock to prevent data races and interleaving.

是的,但是对该锁的特定形式没有要求,C 也没有任何要求使程序可以直接访问该锁,也没有任何标准机制可以这样做。

POSIX documents flockfile() and related functions to allow thread-safe I/O to span multiple calls. Is there an equivalent C function?

没有已发布的 C 语言规范版本记录了 flockfile()ftrylockfile()funlockfile() 的模拟。一个严格符合 C11 或 C17 的程序想要提供防止不同线程调用 I/O 函数的交错将(因为它严格符合)在未定义宏的实现上使用 C 线程库 __STDC_NO_THREADS__。这样的程序可以为此目的使用该库的互斥锁实现。没有标准方法可以直接访问与单个 FILE 对象直接关联的任何锁。

On a related note, is it safe to assume any implementation claiming POSIX conformance will respect flockfile() when using C11 threads.h?

据我所知,POSIX C 语言接口仍然是专门根据 C99 定义的,因此 POSIX 对 C11 线程是盲目的。从这个意义上说,不,假设 POSIX 关于线程行为的规定将适用于 C11 线程是不安全的。

I think most major POSIX-compliant C implementations that support threads.h do so by building on pthreads, which would imply such an assumption is usually safe. However, multithreading is hard, and it would be helpful to know of exceptions.

实际上,我期望 POSIX 系统上的 C11 和更高版本的实现将确保 C11 线程实际上确实具有 POSIX 线程的语义,无论是通过在顶部实现 C11 线程POSIX 个线程或通过其他方式。因此,希望 C11 线程将根据需要与 flockfile() 进行互操作是合理的,但忽略专门探测该细节的单元测试是不合理的。

另请注意,在这种情况下,“通常安全”是表达“不安全”的一种狡猾方式。