2011-01-30 14 views
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; 
} 

,這是輸出我在終端

[email protected]:~/Desktop/testing$ gcc test.c 
[email protected]:~/Desktop/testing$ ./a.out 
lls 
-1--Bad address 
[email protected]:~/Desktop/testing$ ls 
a.out htmlget_ori.c mysocket.cpp Packet Sniffer.c resolutionfinder.c test.c 
[email protected]:~/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)中讀取。 (我這麼認爲)...

感謝您的時間。

+0

「我認爲這是我嘗試訪問的RAM的絕對地址。」你認爲是這樣,根據什麼信息? – 2011-01-30 09:31:20

+1

* @ Anirudh *:確實沒有比指定固定內存位置更好的方法嗎?你能否提供一些關於你想要實現的背景信息? – stakx 2011-01-30 09:41:33

+1

爲什麼不正常使用`read()`,即`unsigned char buffer [3];讀(STDIN_FILENO,&buffer,sizeof(buffer));`??? – 2011-01-30 09:44:22

回答

1

您正在使用分頁的CPU上運行。您的操作系統維護從虛擬地址轉換爲物理地址的頁表。您的進程的頁表不包含虛擬地址2000的任何內容,因此read()通知,並返回-EFAULT

stdin已連接到您的終端設備(/dev/tty)。您的進程從您的shell中繼承該終端,並且shell在進程退出時重新獲取它。

4

2000您試圖作爲地址使用的是特定工藝虛擬地址。沒有任何東西映射到這個範圍的機會是好的;您可以添加以下代碼,看看你的映射當前是:

char cmd[20]; 

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

如果你真的必須訪問系統圍繞2000(我無法想象,你是) RAM,使用iopl(2)系統調用將該地址範圍映射到您的進程內存空間。並注意後果。 :)

對於ls行爲的休息,嘗試添加一個\nprintf()格式字符串,我發現不能正常沖洗輸出可能會導致混淆的前瞻性的互動,或許這只是混亂,而不是徹頭徹尾的奇怪。 :)

0

我只會回答問題1.我不完全理解問題2中的含義,再加上在解決第一個問題時可能會自行處理。

要回答你的問題1,沒有被100%肯定,我敢打賭,(int*)2000指定你的程序的數據段,即該2000僅僅是抵消部分的位置。我之所以這樣認爲的原因是,一般一般,與任何現代操作系統,你幾乎沒有不受限制地訪問物理內存。鏈接器和操作系統的程序加載器爲您處理所有與細分相關的東西 - 您的程序只能看到(虛擬的—參見下文)內存地址的偏移部分。所有與數據有關的事情通常都發生在數據段中;與代碼相關的東西(比如函數調用)通常綁定到代碼段。

正如我所見,您不能保證任何特定的數據結構將位於您的數據段的偏移量2000處。因此,您的read目標幾乎總是無效,因爲它基本上意味着您正在將數據寫入內存中的隨機位置。

P.S.:按虛擬內存地址,我的意思是你的程序的段可能會被操作系統加載到不同的物理內存地址。因此,任何段的偏移量2000(例如)並不總是意味着相同的絕對物理內存地址;而是一個偏移量,即相對於段的基地址,它本身位於任意的物理存儲器地址。