os模块篇(八)

os.openpty()

os.openpty() 是 Python 的 os 模块中的一个函数,用于打开一个新的伪终端对(pseudo-terminal pair)。伪终端对通常用于实现像 shell 这样的交互式环境,它们允许一个程序(例如,一个 shell)作为终端的用户界面运行,而另一个程序(例如,一个 shell 执行的命令)可以像在一个真实的终端中运行一样接收和发送输入/输出。

os.openpty() 返回一个包含两个文件描述符的元组 (master_fd, slave_fd):

  • master_fd 是主设备(master device)的文件描述符,通常用于程序(如 shell)读取和写入,以接收从子设备(slave device)发送的数据并发送数据到子设备。
  • slave_fd 是子设备(slave device)的文件描述符,通常用于另一个程序(如 shell 执行的命令)读取和写入。

以下是一个使用 os.openpty() 的简单示例:

import os
import sys

# 打开一个新的伪终端对
master_fd, slave_fd = os.openpty()

# 使用 os.ttyname() 可以得到与文件描述符相关联的设备名称
print("Master device:", os.ttyname(master_fd))
print("Slave device:", os.ttyname(slave_fd))

# 通常你会在这里 fork 一个子进程,并将 slave_fd 传递给子进程
# 子进程会将其用作其标准输入、输出和错误输出

# 关闭不再需要的文件描述符
os.close(master_fd)
os.close(slave_fd)

在上面的代码中,我们打开了一个新的伪终端对,并打印了主设备和子设备的名称。在实际应用中,你会在 os.openpty() 调用之后 fork 一个子进程,并将子设备的文件描述符传递给它。子进程可以将其用作其标准输入、输出和错误输出,从而允许它与主设备(通常由父进程控制)进行交互。

注意:在真实的使用场景中,你还需要处理诸如信号处理、进程间通信等额外的问题。此外,os.openpty() 在 Windows 上不可用;在 Windows 上,你可能需要使用其他机制(如 winpty)来实现类似的功能

os.pipe()

os.pipe() 是 Python 的 os 模块中的一个函数,它用于创建一个新的管道。管道是一种用于进程间通信的机制,允许一个进程向另一个进程发送数据。

os.pipe() 函数返回一个包含两个文件描述符的元组 (r, w):

  • r 是管道的读端文件描述符,用于从管道中读取数据。
  • w 是管道的写端文件描述符,用于向管道中写入数据。

当从一个进程向管道的写端写入数据时,这些数据可以被另一个进程从管道的读端读取。

下面是一个使用 os.pipe() 创建管道并进行进程间通信的简单示例:

import os

# 创建一个管道
read_end, write_end = os.pipe()

# 创建一个子进程
pid = os.fork()

if pid == 0:  # 子进程
    # 关闭管道的写端
    os.close(write_end)

    # 从管道的读端读取数据
    data = os.read(read_end, 1024)
    print("Child process received:", data.decode())

    # 关闭管道的读端
    os.close(read_end)
    os._exit(0)
else:  # 父进程
    # 关闭管道的读端
    os.close(read_end)

    # 向管道的写端写入数据
    os.write(write_end, b"Hello from parent!")

    # 关闭管道的写端
    os.close(write_end)

    # 等待子进程结束
    os.wait()

在上面的示例中,父进程和子进程通过管道进行通信。父进程向管道的写端写入字符串 “Hello from parent!”,而子进程从管道的读端读取这个字符串并打印出来。

需要注意的是,管道是在进程间进行通信的,而不是线程间。如果你需要在同一进程的多个线程之间进行通信,可能需要使用线程安全的队列或其他同步机制。

此外,管道是半双工的,即数据只能在一个方向上流动。如果你需要双向通信,可能需要使用两个管道,或者考虑使用其他进程间通信机制,如套接字(sockets)、命名管道(named pipes)或共享内存等。

os.pipe2(flags, /)

os.pipe2() 是 Python 3.3 版本中引入的一个函数,它是 os.pipe() 的一个扩展版本。os.pipe2() 提供了更多的选项来配置新创建的管道,通过传递一个标志参数 flags 来实现。

Flags 参数是一个整数,用于指定管道的一些属性。这个参数可以是一些预定义的常量,通过按位或(bitwise OR)操作组合在一起。这些常量通常定义在 <fcntl.h> 头文件中,但在 Python 中可以通过 os 模块访问。

以下是一些可能的 Flags 值(在 Python 中可能以 os.O_ 为前缀):

  • os.O_NONBLOCK: 设置管道为非阻塞模式。这意味着读取或写入管道时,如果没有数据可用或没有足够的空间来写入数据,操作将立即返回而不是阻塞。
  • os.O_CLOEXEC: 设置管道的文件描述符在 exec() 系列函数执行后自动关闭。这有助于防止文件描述符泄漏到新的进程中。

os.pipe2() 返回一个元组,其中包含两个文件描述符,分别是管道的读端和写端,类似于 os.pipe()。

下面是一个使用 os.pipe2() 的示例:

import os

# 创建一个非阻塞的管道
flags = os.O_NONBLOCK
read_end, write_end = os.pipe2(Flags)

# 使用文件描述符进行读写操作
# 注意:因为设置了非阻塞模式,所以读写操作可能立即返回

os.pipe2() 的主要优势在于它允许你更精细地控制管道的行为,特别是在处理多进程或多线程的程序时,你可能需要确保文件描述符在适当的时机被正确关闭,或者希望管道以非阻塞模式运行。

需要注意的是,os.pipe2() 可能在一些旧的操作系统或 Python 版本中不可用。在这种情况下,你可以回退到使用 os.pipe() 并手动设置文件描述符的属性,例如使用 fcntl 模块来设置非阻塞模式。

os.posix_fallocate(fd, offset, len, /)

os.posix_fallocate() 是 Python 3.3 中引入的一个函数,它提供了一个在文件描述符上预分配文件空间的方法,而不需要实际写入任何数据。这个函数是 POSIX 系统(如 Linux 和 macOS)特有的,因此在非 POSIX 系统上可能不可用。

函数的参数如下:

  • fd:一个打开文件的文件描述符(通常是通过 os.open() 获得的)。
  • offset:开始预分配空间的偏移量(以字节为单位)。
  • len:要预分配的空间长度(以字节为单位)。

os.posix_fallocate() 会扩展或截断指定的文件,使其大小至少为 offset + len 字节。如果文件之前的大小小于这个值,那么该函数会在文件中添加额外的空间,但不会写入任何实际的数据。这可以用于提高文件操作的性能,尤其是在你知道文件最终将包含大量数据时。

这里有一个使用 os.posix_fallocate() 的例子:

import os

# 打开一个文件,如果不存在则创建它
fd = os.open('example.dat', os.O_WRONLY | os.O_CREAT)

# 预分配 10 MiB 的空间
size = 10 * 1024 * 1024  # 10 MiB
os.posix_fallocate(fd, 0, size)

# 关闭文件描述符
os.close(fd)

在这个例子中,example.dat 文件将被创建(如果它之前不存在),并且其大小将被扩展为至少 10 MiB,即使实际上没有写入任何数据。

请注意,os.posix_fallocate() 只影响文件在磁盘上的大小,并不保证文件的物理磁盘块都被立即分配。实际的物理分配可能会延迟到文件第一次被写入时。此外,如果文件已经存在并且其大小大于指定的 offset + len,则该函数不会截断文件。如果需要截断文件,可以使用 os.ftruncate()。

os.posix_fadvise(fd, offset, len, advice, /)

os.posix_fadvise() 是 Python 的一个较低级别的系统调用接口,它用于向操作系统提供关于文件访问模式的建议,从而帮助操作系统优化文件访问性能。这个函数是 POSIX(Portable Operating System Interface)系统特有的,因此可能在非 POSIX 系统上不可用。

函数参数如下:

  • fd: 文件描述符,通常是通过 os.open() 或其他系统调用获得的。
  • offset: 开始提供建议的字节偏移量。
  • len: 提供建议的字节长度。
    8 advice: 一个整数,表示给出的建议类型。

advice 参数可以取以下预定义的值之一(这些值通常定义在 <fcntl.h> 头文件中,但在 Python 中可以通过 os 模块访问):

  • os.POSIX_FADV_NORMAL: 没有任何特殊的建议,文件访问遵循常规的文件系统缓存行为。
  • os.POSIX_FADV_RANDOM: 文件访问模式是随机的,文件系统应该避免缓存数据。
  • os.POSIX_FADV_SEQUENTIAL: 文件访问模式是顺序的,文件系统应该尽量缓存数据以优化连续读取。
  • os.POSIX_FADV_WILLNEED: 文件将在不久的将来被访问,文件系统应该预先加载数据到缓存中。
  • os.POSIX_FADV_DONTNEED: 文件在未来不会被访问,文件系统可以丢弃缓存中的数据。
  • os.POSIX_FADV_NOREUSE: 文件数据应该被缓存,但不应该被重新使用来优化其他文件的访问。

这些建议是非强制性的,操作系统可以选择忽略它们。但是,在知道文件访问模式的情况下,使用 os.posix_fadvise() 可以帮助操作系统做出更智能的缓存决策,从而提高文件访问性能。

下面是一个使用 os.posix_fadvise() 的简单示例:

import os

# 打开一个文件
fd = os.open('example.dat', os.O_RDONLY)

# 假设我们即将顺序读取文件的前 1024 字节
offset = 0
length = 1024
advice = os.POSIX_FADV_SEQUENTIAL

# 提供建议
os.posix_fadvise(fd, offset, length, advice)

# 读取文件数据
data = os.read(fd, length)

# 关闭文件描述符
os.close(fd)

# 处理数据...

在这个例子中,我们告诉操作系统我们将要顺序读取文件的前 1024 字节,因此它可能会选择优化这个区域的缓存行为。当然,这个优化在实际应用中可能不会产生显著的影响,但它是一个可以使用的工具,尤其是在处理大文件或需要高性能文件访问的场景中。

os.pread(fd, n, offset, /)

os.pread(fd, n, offset) 是 Python 的一个系统调用接口,用于从文件描述符 fd 中读取数据,并从文件的 offset 偏移量开始读取 n 个字节。这个调用与普通的 os.read(fd, n) 调用不同,因为它不会受到文件描述符的当前文件位置的影响,也不会在读取后更新文件描述符的文件位置。

参数说明:

  • fd: 文件描述符,通常是通过 os.open() 或其他系统调用获得的。
  • n: 要读取的字节数。
  • offset: 从文件的哪个位置开始读取。这是一个绝对位置,而不是相对于当前文件位置的偏移量。

返回值是读取到的字节串(bytes),如果读取的字节数少于请求的 n 个字节,可能是因为文件结束或发生了错误。

os.pread() 常常用于需要精确控制文件读取位置的场景,例如当多个进程或线程需要读取文件的特定部分时,或者当你不希望 read 调用改变文件描述符的文件位置时。

下面是一个使用 os.pread() 的简单示例:

import os

# 打开一个文件
fd = os.open('example.txt', os.O_RDONLY)

# 从文件的第10个字节开始读取10个字节
data = os.pread(fd, 10, 10)

# 处理读取到的数据
print(data)

# 关闭文件描述符
os.close(fd)

在这个例子中,os.pread() 从 example.txt 文件的第10个字节开始读取了10个字节的数据。即使文件描述符 fd 的当前文件位置在其他地方,os.pread() 也会精确地从这个指定的偏移量开始读取。

请注意,os.pread() 在非 POSIX 系统上可能不可用,或者可能需要使用不同的方法来达到相同的效果。在 POSIX 系统上,这个函数通常与 os.pwrite() 配对使用,后者用于从指定的偏移量开始写入数据到文件。

os.posix_openpt(oflag, /)

os.posix_openpt() 是 Python 的一个系统调用,它用于打开一个新的伪终端(pseudo-terminal,通常简称为 pty)的主设备(master device)。伪终端通常用于实现类似 shell 的交互环境,其中程序(如终端仿真器)通过主设备与从设备(slave device,通常是一个伪终端会话)进行通信。

函数的参数 oflag 是一个位掩码,用于指定打开文件的模式和权限,类似于 os.open() 函数中的标志。例如,你可以使用 os.O_RDWR 来打开一个可读写的文件,或者使用 os.O_NONBLOCK 来打开一个非阻塞的文件。

os.posix_openpt() 返回一个文件描述符,你可以使用这个描述符来访问新打开的伪终端的主设备。通常,你还需要使用 os.grantpt() 和 os.unlockpt() 函数来设置从设备的权限和解锁从设备的路径名,以便之后可以使用 os.ptsname() 来获取从设备的路径名。

下面是一个使用 os.posix_openpt(), os.grantpt(), os.unlockpt(), 和 os.ptsname() 的示例:

import os
import pty

# 打开一个新的伪终端的主设备
master_fd = os.posix_openpt(os.O_RDWR | os.O_NOCTTY)

# 获取从设备的路径名
slave_name = os.ptsname(master_fd)

# 设置从设备的权限,使得拥有该伪终端的进程组可以访问
os.grantpt(master_fd)

# 解锁从设备,使得它可以被打开和使用
os.unlockpt(master_fd)

# 此时,你可以使用 master_fd 和 slave_name 来与伪终端从设备进行通信
# 例如,你可以通过 master_fd 向从设备写入数据,或者从从设备读取数据

# 关闭主设备文件描述符
os.close(master_fd)

请注意,伪终端的使用通常涉及比较底层的编程,并且可能需要了解终端 I/O、信号处理等相关知识。在 Python 中,有更高级别的库(如 pty 模块)提供了对伪终端操作的封装,使得使用更加简单。

此外,需要注意的是,os.posix_openpt() 在某些非 POSIX 系统上可能不可用。在不支持该函数的平台上,你可能需要寻找其他方法来创建和使用伪终端。

os.preadv(fd, buffers, offset, flags=0, /)

os.preadv() 是 Python 的一个系统调用接口,它允许从文件描述符 fd 中读取数据,并将数据直接存储在一个由 buffers 参数指定的缓冲区列表中。这个调用类似于 os.readv(),但 os.preadv() 不会在读取后更新文件描述符的文件位置,而是始终从指定的 offset 偏移量开始读取。

参数说明:

  • fd: 文件描述符,通常是通过 os.open() 或其他系统调用获得的。
  • buffers: 一个缓冲区对象的列表,数据会被直接读入这些缓冲区。每个缓冲区通常是一个字节串(bytes)或者可写的字节类型(如 bytearray)。
  • offset: 从文件的哪个位置开始读取。这是一个绝对位置,而不是相对于当前文件位置的偏移量。
  • flags: 一个可选的标志位,用于修改读取行为。通常设置为 0。

返回值是一个元组,包含两个元素:

  • 一个整数,表示实际读取的字节总数。
  • 一个列表,包含与 buffers 参数中相同数量的元素,每个元素表示对应缓冲区中实际填充的字节数。

os.preadv() 通常用于需要高效读取大量数据到多个缓冲区的场景,特别是在处理网络或文件 I/O 时。它允许应用程序减少不必要的内存拷贝,因为数据可以直接从内核空间读入用户空间的缓冲区。

下面是一个使用 os.preadv() 的简单示例:

import os

# 打开一个文件
fd = os.open('example.txt', os.O_RDONLY)

# 创建两个缓冲区来存储读取的数据
buffer1 = bytearray(10)
buffer2 = bytearray(10)
buffers = [buffer1, buffer2]

# 从文件的第20个字节开始读取20个字节到缓冲区
n, read_counts = os.preadv(fd, buffers, 20)

# 处理读取到的数据
print("Read {} bytes:".format(n))
print("Buffer 1: {}, read {} bytes".format(buffer1, read_counts[0]))
print("Buffer 2: {}, read {} bytes".format(buffer2, read_counts[1]))

# 关闭文件描述符
os.close(fd)

在这个例子中,os.preadv() 从 example.txt 文件的第20个字节开始读取了20个字节的数据,并将这些数据直接存储在了 buffer1 和 buffer2 中。n 变量表示实际读取的字节总数,而 read_counts 列表表示每个缓冲区中实际填充的字节数。

请注意,os.preadv() 在非 POSIX 系统上可能不可用,或者可能需要使用不同的方法来达到相同的效果。在使用这些低级系统调用时,还需要注意错误处理和异常安全。

os.ptsname(fd, /)

os.ptsname(fd) 是 Python 的一个系统调用接口,用于获取与给定文件描述符 fd 关联的伪终端(pseudo-terminal,pty)从设备的路径名。通常,这个文件描述符是通过 os.posix_openpt() 或其他相关系统调用打开的伪终端主设备的文件描述符。

参数 fd 是一个已经打开的文件描述符,它必须指向一个有效的伪终端主设备。

os.ptsname() 返回一个字符串,表示与给定文件描述符关联的伪终端从设备的路径名。这个路径名通常是 /dev/pts/X 的形式,其中 X 是一个数字,表示从设备的唯一标识符。

下面是一个使用 os.posix_openpt(), os.grantpt(), os.unlockpt(), 和 os.ptsname() 的完整示例,用于打开一个新的伪终端并获取从设备的路径名:

import os

# 打开一个新的伪终端的主设备
master_fd = os.posix_openpt(os.O_RDWR)

# 解锁从设备
os.unlockpt(master_fd)

# 获取从设备的路径名
slave_name = os.ptsname(master_fd)
print("Slave device name:", slave_name)

# 设置从设备的权限,使得拥有该伪终端的进程组可以访问
os.grantpt(master_fd)

# 在这里,你可以使用 master_fd 和 slave_name 来与伪终端从设备通信
# 例如,你可以通过 master_fd 向从设备写入数据,或者从从设备读取数据

# 关闭主设备文件描述符
os.close(master_fd)

请注意,os.ptsname() 仅适用于伪终端的文件描述符。如果你尝试对非伪终端的文件描述符调用此函数,它可能会引发一个错误。此外,这个函数可能不适用于非 POSIX 系统。

使用伪终端通常涉及到底层的终端 I/O 和信号处理,所以除非你确实需要这种级别的控制,否则通常建议使用更高级的库和接口,如 Python 的 pty 模块,来处理伪终端相关的操作。

os.pwrite(fd, str, offset, /)

os.pwrite() 是 Python 的一个系统调用接口,用于将数据写入到文件描述符 fd 指向的文件或设备中。与 os.write() 不同,os.pwrite() 允许你指定一个 offset 参数,该参数表示从文件的哪个位置开始写入数据。这样,你可以精确地控制数据应该写入文件的哪个部分。

参数说明:

  • fd: 文件描述符,通常是通过 os.open() 或其他系统调用获得的。
  • str: 要写入的数据,通常是一个字节串(bytes)。
  • offset: 从文件的哪个位置开始写入数据。这是一个绝对位置,而不是相对于当前文件位置的偏移量。

os.pwrite() 返回一个整数,表示实际写入的字节数。

请注意,os.pwrite() 通常用于那些需要精确控制写入位置的场景,比如对设备文件或某些特殊文件的操作。对于普通文件,通常使用 os.write() 或 os.lseek() 和 os.write() 的组合来写入数据。

下面是一个使用 os.pwrite() 的简单示例:

import os

# 打开一个文件,准备写入数据
fd = os.open('example.txt', os.O_WRONLY | os.O_CREAT)

# 要写入的数据
data = b'Hello, World!'

# 从文件的第10个字节位置开始写入数据
n = os.pwrite(fd, data, 10)

# 确认写入的字节数
print(f"Wrote {n} bytes to the file.")

# 关闭文件描述符
os.close(fd)

在这个例子中,os.pwrite() 将字节串 data 从 example.txt 文件的第10个字节位置开始写入。如果文件原本小于10个字节,那么文件会被扩展以容纳新写入的数据。

需要注意的是,os.pwrite() 是针对底层文件描述符的操作,因此在使用时需要确保你对文件或设备的操作有正确的理解,并且正确处理可能出现的错误和异常。此外,不是所有的文件类型都支持使用 offset 参数进行写操作,这取决于文件系统的实现和文件的类型。

os.pwritev(fd, buffers, offset, flags=0, /)

os.pwritev() 是 Python 的一个系统调用接口,用于将数据从多个缓冲区写入到文件描述符 fd 指向的文件或设备中。与 os.writev() 类似,os.pwritev() 允许应用程序将数据直接从一个缓冲区列表中写入,而不是分多次调用 os.write()。不过,os.pwritev() 还允许你指定一个 offset 参数,以从文件的特定位置开始写入数据。

参数说明:

  • fd: 文件描述符,通常是通过 os.open() 或其他系统调用获得的。
  • buffers: 一个缓冲区对象的列表,数据会从这些缓冲区中读取并写入文件。每个缓冲区通常是一个字节串(bytes)或者可读的字节类型(如 bytearray)。
  • offset: 从文件的哪个位置开始写入数据。这是一个绝对位置,而不是相对于当前文件位置的偏移量。
  • flags: 一个可选的标志位,用于修改写入行为。通常设置为 0。

os.pwritev() 返回一个整数,表示实际写入的字节总数。

与 os.pwrite() 一样,os.pwritev() 通常用于需要精确控制写入位置的场景,比如对设备文件或某些特殊文件的操作。使用 os.pwritev() 可以减少系统调用的次数,从而提高数据写入的效率。

下面是一个使用 os.pwritev() 的简单示例:

import os

# 打开一个文件,准备写入数据
fd = os.open('example.txt', os.O_WRONLY | os.O_CREAT)

# 创建两个缓冲区,包含要写入的数据
buffer1 = b'Hello'
buffer2 = b'World'
buffers = [buffer1, buffer2]

# 从文件的第10个字节位置开始写入数据
n = os.pwritev(fd, buffers, 10)

# 确认写入的字节数
print(f"Wrote {n} bytes to the file.")

# 关闭文件描述符
os.close(fd)

在这个例子中,os.pwritev() 将 buffer1 和 buffer2 中的数据从 example.txt 文件的第10个字节位置开始写入。如果文件原本小于10个字节,那么文件会被扩展以容纳新写入的数据。

请注意,os.pwritev() 和 os.pwrite() 一样,是针对底层文件描述符的操作,因此在使用时需要确保你对文件或设备的操作有正确的理解,并且正确处理可能出现的错误和异常。此外,不是所有的文件类型都支持使用 offset 参数进行写操作,这取决于文件系统的实现和文件的类型。

  • 28
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熊猫Devin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值