Python下的读/写/查找操作

时间:2017-12-07 15:08:30

标签: python c linux python-2.7 linux-device-driver

在Linux系统上创建角色设备时,我使用Python及其基本文件操作与它进行了交互。

在遇到几次崩溃之后,我开始打印调试消息并注意到一个奇怪的行为:似乎Python"优化"文件操作很奇怪。

让我们看一个例子;这是交互的基本代码和输出:

内核模块

// Several includes and kernel module initialization

static ssize_t dev_read(struct file *filep, char *buffer, size_t len, long long *offset){
    printk(KERN_INFO "[DEBUGGER] - dev_read with len: %d, offset: 0x%llx.\n", len, offset[0]);
    return len;
}

static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, long long *offset){
    printk(KERN_INFO "[DEBUGGER] - dev_write with len: %d, offset: 0x%llx.\n", len, offset[0]);
    return len;
}

static long long dev_llseek(struct file *filep, long long offset, int orig){
    printk(KERN_INFO "[DEBUGGER] - dev_llseek with offset: 0x%llx, orig: %d\n", offset, orig);
    return offset;
}

static int dev_release(struct inode *inodep, struct file *filep){
    return 0; // Success
}

static int dev_open(struct inode *inodep, struct file *filep){
    return 0; // Success
}

static struct file_operations fops =
{
   .open = dev_open,
   .read = dev_read,
   .write = dev_write,
   .release = dev_release,
   .llseek = dev_llseek,
};

int init_module(void){
   // Code to create character device
   return 0;
}

void cleanup_module(void){
   // Code to delete character device
}

的Python

with open("/dev/chardevice", "r+b") as character:
   character.seek(1)
   character.read(4)
   character.seek(0x7f123456)
   character.read(20)
   character.write("\xff" * 4)

输出

# seek(1)
[DEBUGGER] - dev_llseek with offset: 0x0, orig: 0
[DEBUGGER] - dev_read with len: 1, offset: 0x0.
[DEBUGGER] - dev_llseek with offset: 0x1, orig: 0
# read(4)
[DEBUGGER] - dev_read with len: 4, offset: 0x0.
# seek(0x7f123456)
[DEBUGGER] - dev_llseek with offset: 0x7f123000, orig: 0
[DEBUGGER] - dev_read with len: 1110, offset: 0x0.
# read(20)
[DEBUGGER] - dev_read with len: 4096, offset: 0x0.
# write("\xff" * 4)
[DEBUGGER] - dev_write with len: 4, offset: 0x0.

很明显,基本文件操作不直接转换为文件上的相同操作,最明显的例子是寻求0x7f123000而不是0x7f123456,读取4096字节,而只读取20字节的读取。

这提出了以下问题:

  • 为什么这是一个功能?
  • 它实现了哪些优化,因为它大多数看起来都不是一个好的"下一个操作"预测?
  • 是否记录在任何地方,知道在预先编写读/写功能时会发生什么?
  • 除了对这个领域的纯粹兴趣之外,我仍然希望使用Python来更容易访问 - 那么有没有办法禁用这种优化,并强制Python的行为就像执行这些操作的C代码一样?

谢谢!

2 个答案:

答案 0 :(得分:4)

Python的文件对象实际上是double overflow = 0; int left = items.Count; // loop in order of ascending value foreach (var item in items.OrderBy(c => c.Value)) { // calculate part of overflow to assign to this item, based on total and how much items still left var overflowForItem = overflow / left; // assign a bit less than expected if there is overflow item.Percent = (item.Value - overflowForItem) / (double)sum; // reduce overflow (we just assigned part of it above) overflow -= overflowForItem; if (item.Percent < minPercentage) { overflow += (minPercentage - item.Percent) * sum; item.Percent = minPercentage; } left--; } 对象(用C语言)的包装器,因此它们是缓冲流。由于缓冲,Python对文件的操作不会将它们转换为具有相同参数的系统调用,而是尝试优化请求时间(对于当前和未来的操作)。

方法FILE* accepts 缓冲参数作为3d参数。传递0应该禁用缓冲,因此python会将所有文件的请求直接转换为底层系统:

open()

答案 1 :(得分:0)

我不确定这是什么情况,但我认为这与读取一个字节的时间代价与读取整个扇区相同,所以为什么不从磁盘读取整个扇区(或者也许你甚至不能要求读取比基础系统的扇区大小更少的字节数