2

所以这是我试图运行的代码:

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

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

谢谢你的时间。

4

2 回答 2

4

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

char cmd[20];

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

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

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

于 2011-01-30T09:24:35.303 回答
1

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

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

于 2011-01-30T12:09:45.943 回答