不间断的读/写调用

发布于 2024-09-11 19:29:42 字数 237 浏览 12 评论 0原文

在 Linux 上的 C 编程冒险过程中的某个时刻,我遇到了一些标志(可能是 ioctl/fcntl?),这些标志使文件描述符上的读写操作不间断。

不幸的是,我不记得如何做到这一点,也不记得我在哪里读过它。任何人都可以透露一些信息吗?

Update0

为了优化我的查询,我追求相同的阻塞并保证 fwrite()fread() 提供,无用户空间缓冲。

At some point during my C programming adventures on Linux, I encountered flags (possibly ioctl/fcntl?), that make reads and writes on a file descriptor uninterruptible.

Unfortunately I cannot recall how to do this, or where I read it. Can anyone shed some light?

Update0

To refine my query, I'm after the same blocking and guarantees that fwrite() and fread() provide, sans userspace buffering.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

把梦留给海 2024-09-18 19:29:42

您可以通过确保所有信号处理程序都使用 SA_RESTART 安装来避免来自 read()write()EINTR > sigaction() 的标志。

然而,这并不能保护您免受读/写的影响。这只能通过将 read() / write() 放入循环中来实现(除了必须已提供给 的缓冲区之外,它不需要额外的缓冲区) code>read() / write() 调用。)

这样的循环如下所示:

/* If return value is less than `count', then errno == 0 indicates end of file,
 * otherwise errno indicates the error that occurred. */
ssize_t hard_read(int fd, void *buf, size_t count)
{
    ssize_t rv;
    ssize_t total_read = 0;

    while (total_read < count)
    {
        rv = read(fd, (char *)buf + total_read, count - total_read);

        if (rv == 0)
            errno = 0;

        if (rv < 1)
            if (errno == EINTR)
                continue;
            else
                break;

        total_read += rv;
    }

    return rv;
}

You can avoid EINTR from read() and write() by ensuring all your signal handlers are installed with the SA_RESTART flag of sigaction().

However this does not protect you from short reads / writes. This is only possible by putting the read() / write() into a loop (it does not require an additional buffer beyond the one that must already be supplied to the read() / write() call.)

Such a loop would look like:

/* If return value is less than `count', then errno == 0 indicates end of file,
 * otherwise errno indicates the error that occurred. */
ssize_t hard_read(int fd, void *buf, size_t count)
{
    ssize_t rv;
    ssize_t total_read = 0;

    while (total_read < count)
    {
        rv = read(fd, (char *)buf + total_read, count - total_read);

        if (rv == 0)
            errno = 0;

        if (rv < 1)
            if (errno == EINTR)
                continue;
            else
                break;

        total_read += rv;
    }

    return rv;
}
抚笙 2024-09-18 19:29:42

您是否希望在读/写时禁用中断,或者保证在您读/写文件时没有其他人会读/写该文件?

对于第二个,您可以使用fcntl()的F_GETLK、F_SETLK和F_SETLKW分别获取、释放和测试记录锁。然而,由于 POSIX 锁只是建议性的,Linux 并不强制执行它们——它只在协作进程之间有意义。

第一个任务涉及深入研究零环并禁用本地处理器上的中断(或者全部,如果您使用的是 SMP 系统)。完成后请记住再次启用它们!

Do you wish to disable interrupts while reading/writing, or guarantee that nobody else will read/write the file while you are?

For the second, you can use fcntl()'s F_GETLK, F_SETLK and F_SETLKW to acquire, release and test for record locks respectively. However, since POSIX locks are only advisory, Linux does not enforce them - it's only meaningful between cooperating processes.

The first task involves diving into ring zero and disabling interrupts on your local processor (or all, if you're on an SMP system). Remember to enable them again when you're done!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文