小编dar*_*dar的帖子

捕获信号时中断系统调用

从阅读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()在执行信号处理程序后没有恢复,最终导致所有可用数据(毕竟可用)被返回?

kernel signals system-calls architecture

34
推荐指数
1
解决办法
3万
查看次数

提取与“sed”匹配的正则表达式而不打印周围的字符

致所有的“sed”医生:

你怎么能得到'sed'来提取它在一行中匹配的正则表达式?

换句话说,我只想要与正则表达式相对应的字符串,其中包含行中的所有非匹配字符都被剥离。

我尝试使用如下所示的反向引用功能

regular expression to be isolated 
         gets `inserted` 
              here     
               |
               v  
 sed -n 's/.*\( \).*/\1/p 
Run Code Online (Sandbox Code Playgroud)

这适用于某些表达式,例如

 sed -n 's/.*\(CONFIG_[a-zA-Z0-9_]*\).*/\1/p 
Run Code Online (Sandbox Code Playgroud)

它巧妙地提取了所有以 'CONFIG_ ....' 开头的宏名称(在某些 '*.h' 文件中找到)并逐行打印出来

          CONFIG_AT91_GPIO
          CONFIG_DRIVER_AT91EMAC
                   .
                   .   
          CONFIG_USB_ATMEL
          CONFIG_USB_OHCI_NEW
                   .
                 e.t.c. 
Run Code Online (Sandbox Code Playgroud)

但是上面的内容分解为类似的东西

  sed -n 's/.*\([0-9][0-9]*\).*/\1/p 
Run Code Online (Sandbox Code Playgroud)

这总是返回个位数,如

                 7
                 9
                 .
                 .  
                 6
Run Code Online (Sandbox Code Playgroud)

而不是提取连续的数字字段,例如。

              8908078
              89670890  
                 .
                 .  
                 .
               23019   
                 .
               e.t.c.  
Run Code Online (Sandbox Code Playgroud)

PS:我将非常感谢关于如何在“sed”中实现这一点的反馈。我知道如何使用“grep”和“awk”来做到这一点我想知道我对“sed”的理解(尽管有限)是否有漏洞,以及是否有办法在我
拥有的“sed”中做到这一点简直被忽视了。

sed

27
推荐指数
3
解决办法
6万
查看次数

使用户空间文本段从 0x8048000 开始的基本原理

我在某处读到(至少从 Linux v. 2.6 开始)所有用户空间代码都放置在虚拟内存地址空间中的加载地址 0x8048000 处。

我自己的观察证实了这一点。我做了一个

cat /proc/......../maps
Run Code Online (Sandbox Code Playgroud)

对于多个进程,进程'程序的第一部分text总是从'0x8048000'开始。

此外,C 库启动代码和所有其他运行时好东西似乎都映射在此默认值之后。

这构成了近 128 M 的地址空间,考虑到 0xC0000000 - 0x8048000 仍然是用户空间内容的几乎 3G 地址空间,这并不多。

所以我的问题是为什么?

我们正在处理虚拟地址,与其他程序的干扰或重叠是由 VM 工作方式的定义排除的。

0x00000000 到 0x8048000 范围内是否有一些固定/默认映射?

除了默认起始地址落在页面边界这一事实之外,选择这个数字而不是任何其他值的理由是什么?

linux process memory elf virtual-memory

5
推荐指数
0
解决办法
1310
查看次数