首页 > 解决方案 > 即使使用 O_EXCL,打开的文件也太多

问题描述

我正在尝试编写一个函数,该函数能够确定调用它的进程是否是第一个这样做的,而不使用任何锁。

这是我目前的实现。

def is_first_process(path):
    filename = os.path.join(path, "first.file")
    try:
        fd = os.open(filename, os.O_CREAT | os.O_EXCL | os.O_WRONLY)
        os.close(fd)
        return True
    except FileExistsError:
        return False

我像这样测试上面的函数:

def test_is_first_process():
    path = "/tmp/first_process"
    shutil.rmtree(path, ignore_errors=True)
    process_list = []

    def helper(fn, arg, shared_list):
        shared_list.append(fn(arg))

    for _ in range(1000):
        makedirs(path)
        manager = Manager()
        results = manager.list()
        for i in range(1000):
            p = Process(target=helper, args=(is_first_process, path, results))
            p.start()
            process_list.append(p)

        for p in process_list:
            p.join()

        assert results.count(True) == 1
        shutil.rmtree(path, ignore_errors=True)

对于大 m*n,测试错误并出现以下错误:

E OSError: [Errno 24] Too many open files

但不适用于较小的值(m*n < 100)。

我对 os.O_EXCL 标志的理解是,FileExistsError如果它已经存在,它会引发。

我对这个标志的理解不正确吗?如何正确实现和测试可以确定写入目录的第一个进程的函数?

标签: python

解决方案


我认为您可能误解了您所看到的错误。关于的错误消息Too many open files意味着它所说的,您同时打开了太多文件。不一定您的一个文件一次被打开多次。

可能是处理进程间通信的多处理代码导致您试图一次启动的 1000 个单独进程出现问题。那是很多过程!

许多操作系统限制每个进程可以打开多少文件,并且通常还限制每个用户登录,因此即使在大量进程中的每个进程中只打开几个文件也可能是一个问题。您可能可以使用ulimit -n或类似的配置程序来修改系统上的限制。

但真正的问题是,为什么您认为需要一次测试 1000 个进程?即使在大型系统上,您也可能不会拥有那么多 CPU 内核,因此这些进程中的大多数必然会处于休眠状态,而只有少数进程在运行。我建议您使用最多是系统内核数的一小部分(例如 2 倍)的进程进行测试,再多的进程只会浪费您的时间。


推荐阅读