【问题标题】:could not understand the behavior of read system call无法理解读取系统调用的行为
【发布时间】:2011-06-18 01:05:54
【问题描述】:

这就是我要运行的代码:

#include<fcntl.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#include<unistd.h>

int main(){

  int ret;

  ret = read(STDIN_FILENO,(int*)2000,3);
  printf("%d--%s\n",ret,strerror(errno));

  return 0;
}

这是我在终端得到的输出

anirudh@anirudh-Aspire-5920:~/Desktop/testing$ gcc test.c 
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ ./a.out 
lls
-1--Bad address
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ ls
a.out  htmlget_ori.c  mysocket.cpp  Packet Sniffer.c  resolutionfinder.c  test.c
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ 

问题 1: 当我在读取调用 read(STDIN_FILENO,(int*)2000,3); 中键入地址 2000 时 那么地址在哪里。我认为这是我试图访问的 RAM 的绝对地址。我是对的还是它偏移并被添加到堆栈段基地址。我不知道。该程序没有给我SEGFAULT 内存违规,而是给我Bad address

问题 2: 好的,所以当我输入 lls 并且 bash 执行该“lls”的“ls”部分时,代码会崩溃。原因是代码在读取第一个“l”后崩溃,其余的“ls”部分由 bash 执行。但是为什么 bash 正在执行左侧的“ls”部分。为什么 bash 这样做是因为我的代码崩溃了,即使 bash 是它的父进程,它也不应该从我编写的代码打开的文件描述符 (STDIN_FILNO) 中读取。 (我想是的)...

感谢您的宝贵时间。

【问题讨论】:

  • "我认为这是我尝试访问的 RAM 的绝对地址。"你这么认为,基于什么信息?
  • @Anirudh:真的没有比指定固定内存位置更好的方法了吗?您能否提供一些有关您想要实现的目标的背景信息?
  • 为什么不正常使用read(),即unsigned char buffer[3]; read(STDIN_FILENO, &amp;buffer, sizeof(buffer));???

标签: c offset segment memory-address


【解决方案1】:

您尝试用作地址的2000特定于进程的 虚拟地址。没有任何东西映射到该范围内的机会很大;您可以添加此代码以查看您当前的映射是什么:

char cmd[20];

sprintf(cmd, "pmap -x %i", getpid());
printf("%s\n", cmd);
system(cmd);

如果您真的必须访问2000 周围的系统 RAM(我无法想象您是这样),请使用iopl(2) 系统调用将该地址范围映射到您的进程中内存空间。并注意后果。 :)

至于ls 的其余行为,请尝试将\n 添加到您的printf() 格式字符串中,我发现不正确刷新输出会导致看起来令人困惑的交互,也许这只是令人困惑,而不是彻头彻尾的奇怪。 :)

【讨论】:

  • 即使我给它(int*) 0 它也不起作用。所以如果我认为它是我的数据段的一部分,那么我的代码应该被允许在偏移量 0 处读取内存。
  • @Anirudh Tomer,大多数操作系统默认拒绝所有访问位于0x0 的数据页面,作为查找NULL 指针错误的简单方法。尝试从您的 shell 中执行 pmap -x $$ 以更好地了解内存映射的工作原理。
  • iopl() 不允许访问分配给较低环的内存。它可以访问 IO 端口和一些特权指令。
【解决方案2】:

您正在使用分页的 CPU 上运行。您的操作系统维护从虚拟地址转换为物理地址的页表。您的进程的页表不包含虚拟地址 2000 的任何内容,因此 read() 通知,并返回 -EFAULT

stdin 已连接到您的终端设备 (/dev/tty)。您的进程从您的 shell 继承该终端,并且 shell 在进程退出时将其取回。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 2016-02-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多