从阅读read()和write()调用上的手册页来看,这些调用似乎会被信号中断,无论它们是否必须阻塞。
特别地,假设
O_NONBLOCK 没有设置(即在阻塞模式下运行)read()系统调用以从设备读取,结果在内核空间中执行内核控制路径。read()在内核空间中执行时,先前为其安装处理程序的信号被传递到该进程并调用其信号处理程序。阅读SUSv3 'System Interfaces volume (XSH)' 中的手册页和相应部分,您会发现:
一世。如果 aread()在读取任何数据之前被信号中断(即它必须阻塞,因为没有数据可用),它返回 -1 并errno设置为 [EINTR]。
ii. 如果 aread()在成功读取一些数据后被信号中断(即可以立即开始服务请求),它返回读取的字节数。
问题 A):
我是否正确地假设在任何一种情况下(阻止/不阻止)信号的传递和处理对read()?
案例一。似乎可以理解,因为阻塞read()通常会将进程置于TASK_INTERRUPTIBLE状态,以便在传递信号时,内核将进程置于TASK_RUNNING状态。
但是,当read()不需要阻塞(情况 ii.)并且正在内核空间中处理请求时,我会认为信号的到达及其处理将是透明的,就像硬件的到达和正确处理一样中断会。特别是我会假设,在传递信号时,进程将被临时置于用户模式以执行其信号处理程序,它最终将从该处理程序返回以完成处理中断的read()(在内核空间中),以便read()运行其过程完成之后,进程返回到调用read()(在用户空间中)之后的点,结果读取所有可用字节。
但是二。似乎暗示read()被中断,因为数据立即可用,但它返回仅返回部分数据(而不是全部)。
这让我想到了我的第二个(也是最后一个)问题:
问题 B):
如果我在 A) 下的假设是正确的,为什么会read()被中断,即使它不需要阻塞,因为有数据可以立即满足请求?换句话说,为什么read()在执行信号处理程序后没有恢复,最终导致所有可用数据(毕竟可用)被返回?
这个问题有两个方面:
首先,您如何手动从 USB 设备上分离驱动程序并连接不同的驱动程序?例如,我有一个连接时自动使用 USB 存储驱动程序的设备。
Vendor Id: xxxx
Product Id: xxxx
...
Number of Interfaces: 2
Interface Number: 0
Name: usb-storage
Number of Endpoints: 2
...
Interface Number: 1
Name: (none)
Number of Endpoints: 2
...
Run Code Online (Sandbox Code Playgroud)
我不想使用 USB 存储驱动程序,因此在我的应用程序中,我使用该libusb库来分离 USB 存储驱动程序,然后声明该接口。然后,我可以在我的 USB 设备和我的主机 Linux 系统上运行的应用程序之间发送数据。
如何在应用程序之外手动分离驱动程序?
其次,如何自动分配驱动程序以附加到设备插件上?我目前有一个 udev 规则设置来自动设置设备权限:
SUBSYSTEM=="usb", ATTR{idVendor}=="xxxx", MODE="0666"
Run Code Online (Sandbox Code Playgroud)
我可以使用 udev 规则为 USB 设备上的特定接口分配驱动程序吗?例如,如果我希望在接口 0 上自动使用 usbnet 模块而不是 usb-storage,这在 udev 中可能吗?
当我运行使用大部分 16GB 物理内存的应用程序时,Linux 内核会从内存中换出大部分页面。应用程序完成后,每个操作(键入命令、切换工作区、打开新网页等)都需要很长时间才能完成,因为首先需要从交换中读回相关页面。
有没有办法告诉 Linux 内核将页面从交换区复制回物理内存,而无需手动接触(和等待)每个应用程序?我运行了很多应用程序,所以等待总是很痛苦。
我经常swapoff -a && swapon -a用来使系统再次响应,但这会从交换中清除页面,因此下次运行脚本时需要再次写入它们。
是否有内核接口(可能使用 sysfs)来指示内核从交换中读取所有页面?
编辑:我确实在寻找一种方法来使所有交换交换缓存。(感谢德罗伯特!)
[PS serverfault.com/questions/153946/...和serverfault.com/questions/100448/...是相关主题,但没有解决如何让Linux内核在不清除swap的情况下将页面从swap复制回内存的问题。]
Linux 编程接口显示了进程的虚拟地址空间的布局。图中的每个区域都是一个段吗?
从了解 Linux 内核,
下面的意思是MMU中的分段单元将段和段内的偏移量映射到虚拟内存地址,然后分页单元将虚拟内存地址映射到物理内存地址是否正确?
内存管理单元(MMU)通过称为分段单元的硬件电路将逻辑地址转换为线性地址;随后,称为分页单元的第二个硬件电路将线性地址转换为物理地址(见图 2-1)。
那为什么说Linux不使用分段而只使用分页呢?
分段已包含在 80x86 微处理器中,以鼓励程序员将他们的应用程序拆分为逻辑相关的实体,例如子程序或全局和本地数据区。但是, Linux 以非常有限的方式使用分段。实际上,分段和分页是有些多余的,因为两者都可以用来分隔进程的物理地址空间:分段可以为每个进程分配不同的线性地址空间,而分页可以将相同的线性地址空间映射到不同的物理地址空间. 出于以下原因,Linux 更喜欢分页而不是分段:
• 当所有进程使用相同的段寄存器值时,即当它们共享同一组线性地址时,内存管理更简单。
• Linux 的设计目标之一是可移植到广泛的体系结构中。特别是 RISC 体系结构对分段的支持有限。
2.6 版本的 Linux 仅在 80x86 架构需要时才使用分段。
MemTest86+(Ubuntu 13.04 附带的版本)说
Failing address: 002f796c48 - 759.5 MB
Run Code Online (Sandbox Code Playgroud)
我应该在memmap内核参数中指定什么来绕过这个区域?
我试过运行memtester 770MB,它说一切正常,所以看起来 MemTest 的指示从一开始就意味着第 759.5 MB 中的错误。
如何解释这个 MemTest 指示来配置memmap?
我现在没有钱购买新的 RAM,而且错误似乎是单一的,所以我希望我可以覆盖它。
我注意到内核中有以下选项:CONFIG_DEVTMPFS
Device Drivers -> Generic Driver Options -> Maintain devtmpfs to mount at /dev
Run Code Online (Sandbox Code Playgroud)
我看到它在 Debian 发行版内核中默认启用 3.2.0-4-amd64
我试图了解这个选项带来了什么不同。如果没有此选项,/dev则挂载为tmpfs,使用此选项,则挂载为devtmpfs。除此之外,我看不出有什么不同。
在help没有明确对我来说之一:
这会在启动初期创建一个 tmpfs/ramfs 文件系统实例。在此文件系统中,内核驱动程序核心维护设备节点及其默认名称和所有注册设备的权限,这些设备具有分配的主要/次要编号。
它提供了一个功能齐全的 /dev 目录,通常 udev 在上面运行,管理权限并添加有意义的符号链接。
在非常有限的环境中,它可能会在没有任何进一步帮助的情况下提供足够功能的 /dev。它还允许简单的救援系统,并可靠地处理动态的主要/次要号码。
有人可以解释使用CONFIG_DEVTMPFS与标准之间的区别/dev吗?
简而言之,我在内核中有一个物理地址0x250000000(9,932,111,872 或),它显然与 4KiB(页面大小)对齐。当我使用内核__va()函数获取内核虚拟地址时,我得到类似0xf570660f(每次启动时不同)的信息,该地址未与 4KiB 对齐。
我使用的是 64 位系统,因此没有 HIGHMEM,并且我认为由于线性内存模型,4KiB 对齐的物理地址的虚拟地址也应该是 4KiB 对齐的。我错过了什么?虚拟地址不应该是吗phys_addr + PAGE_OFFSET?或者是sparsemem的影响?但也许它也应该是 4KiB 对齐的?
以下是更多详细信息:
我的工作环境是在 x86 64 位 QEMU VM 上。我正在尝试在模式下使用 PMEMDEV-DAX作为普通内存。我可以得到它的物理起始地址(0x250000000),已经确认是正确的。然后我需要将它转移到内核空间中的虚拟地址,以便我可以根据需要使用它。这是一些代码:
static long nvpc_map_whole_dev(struct dax_device *dax_dev, void **kaddr, pfn_t *pfn)
{
// get the device
struct dev_dax_nvpc *dax_nvpc = (struct dev_dax_nvpc *)dax_get_private(dax_dev);
// get the virtual address and the pfn_t
*kaddr = __va(dax_nvpc->phys_start);
*pfn = phys_to_pfn_t(dax_nvpc->phys_start, PFN_MAP); …Run Code Online (Sandbox Code Playgroud) 我的经验是,在物理内存耗尽之前,Linux 可以正常工作。一旦使用交换空间,性能就会严重下降并且 GUI 变得无响应。
这个问题不限于特定的发行版或桌面,因为我已经尝试了一些(问题仍然存在)。
我该怎么办?
如果这个问题过于面向程序员,请告诉我。我想知道是否有人熟悉Linux 2.6上open()系统调用的O_DIRECT标志?Linus 贬低它的使用,但高性能文件写入似乎表明它的使用。我想知道任何现实世界的经验和建议。
更多信息:我正在使用的应用程序确实维护着自己的缓存,这样做的速度平均提高了 5 倍或更多。写入文件时,缓存的内容必须写出到文件系统缓存,这似乎是多余的,而且是一个性能问题。
kernel ×10
linux ×6
memory ×3
performance ×2
swap ×2
architecture ×1
devices ×1
drivers ×1
files ×1
io ×1
linux-kernel ×1
programming ×1
ram ×1
signals ×1
sysfs ×1
system-calls ×1
udev ×1
usb ×1