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:さて、入力をasとして指定すると、コードがクラッシュしlls、bashがその「lls」の「ls」部分を実行します。その理由は、最初の「l」を読み取った後にコードがクラッシュし、残りの「ls」の部分がbashによって実行されるためです。しかし、なぜbashが左側の「ls」部分を実行しているのか。コードがクラッシュし、bashがその親プロセスであったとしても、作成したコードによって開かれたファイル記述子(STDIN_FILNO)から読み取るべきではないため、bashがそうするのはなぜですか。( そう思います)...

御時間ありがとうございます。

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動作については、フォーマット文字列にを追加してみ\nてください。printf()出力を適切にフラッシュしないと、混乱しているように見えるインタラクションにつながる可能性があります。おそらく、これはまったく奇妙なことではなく、単に混乱しているだけです。:)

于 2011-01-30T09:24:35.303 に答える
1

ページングを使用してCPUで実行しています。OSは、仮想アドレスから物理アドレスに変換するページテーブルを維持しています。プロセスのページテーブルには仮想アドレス2000のページテーブルが含まれていないため、read()通知してを返します-EFAULT

stdin端末デバイスに接続されています(/dev/tty)。プロセスはシェルからその端末を継承し、シェルはプロセスの終了時に端末を取得します。

于 2011-01-30T12:09:45.943 に答える