无法理解读取系统调用的行为
所以这是我试图运行的代码:
#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
,而是给我错误地址
问题2:好的,所以当我给出输入时代码崩溃了as lls
并且 bash 执行该“lls”的“ls”部分。原因是代码在读取第一个“l”后崩溃,其余“ls”部分由bash执行。但为什么 bash 执行左边的“ls”部分。为什么 bash 这样做是因为我的代码崩溃了,即使 bash 是它的父进程,它也不应该从我编写的代码打开的文件描述符(STDIN_FILNO)中读取。 (我想是的)...
感谢您的宝贵时间。
So this is the code I am trying to run:
#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;
}
and this is the output I get at the terminal
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$
Question 1: When I type the address 2000 in th read call read(STDIN_FILENO,(int*)2000,3);
then where does the address lies. I think this is the absolute address of the RAM that I am trying to access. am I right or is it offset and is added to the Stack Segment Base Address. I do not know. The program is not giving me a SEGFAULT
for memory violation rather gives me Bad address
Question 2: Okay so the code crashes when I give the input as lls
and bash executes the "ls" part of that "lls". The reason is that the code crashes after reading the first "l" and the rest "ls" part is executed by bash. but why bash is executing the left "ls" part. Why is bash doing so because my code is crashed and even if bash was its parent process it should not read from the file-descriptor (STDIN_FILNO) opened by the code I wrote. ( I think so)...
Thanks for your time.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您尝试用作地址的
2000
是特定于进程的虚拟地址。很可能没有任何内容映射到该范围;您可以添加此代码来查看当前的映射:如果您确实必须访问
2000
左右的系统 RAM(我无法想象您是这样),使用 iopl(2) 系统调用将该地址范围映射到进程内存空间。并注意后果。 :)至于其余的 ls 行为,请尝试将
\n
添加到您的printf()
格式字符串中,我发现不正确地刷新输出可能会导致看起来令人困惑的交互,也许这只是令人困惑,而不是完全奇怪。 :)The
2000
that you are trying to use as an address is a process-specific virtual address. Chances are good that nothing is mapped into that range; you can add this code to see what your mappings currently are:If you really must gain access to system RAM around
2000
(and I can't imagine that you are), use theiopl(2)
system call to map that address range into your process memory space. And beware the consequences. :)As for the rest of the
ls
behaviour, try adding a\n
to yourprintf()
format string, I've found that not properly flushing output can lead to confusing-looking interaction, perhaps this is just confusing, rather than outright strange. :)您正在使用分页功能的 CPU 上运行。您的操作系统维护从虚拟地址转换为物理地址的页表。您的进程的页表不包含虚拟地址 2000 的任何内容,因此
read()
会注意到,并返回-EFAULT
。stdin
已连接到您的终端设备 (/dev/tty
)。您的进程从 shell 继承该终端,并且 shell 在进程退出时将其取回。You are running on a CPU with paging. Your OS maintains page tables which translate from virtual to physical addresses. The page table for your process doesn't contain anything for virtual address 2000, so
read()
notices, and returns-EFAULT
.stdin
is connected to your terminal device (/dev/tty
). Your process inherits that terminal from your shell, and the shell gets it back on process exit.