1

こんにちは、特定のデバイスの読み取りと書き込みを行う char ドライバーを作成しています。私は初心者なので、これはオープン、読み取り、書き込み、解放などの最も単純なプロトコルのみを使用する、非常にシンプルで簡単な char ドライブです。ドライバーをテストするために、次のプログラムを使用しています... 以下は、ユーザー空間プログラムのソースです。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <signal.h>
#include <poll.h>

int main(void){
int num;
char *buff;
FILE *fd = fopen("/dev/hi","a+");
num = fprintf(fd,"this is sentence 1 !!");
num = fprintf(fd,"this is sentence 2 !!");
num = fprintf(fd,"this is sentence 3 !!");
num = fprintf(fd,"this is sentence 4 !!");
num = fprintf(fd,"this is sentence 5 !!");
buff = malloc(sizeof(char) * num+1);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
free(buff);
close(fd);
return 0;
}

ここで、ドライバーがどのように機能するかは重要ではありませんが、読み取りメソッドと書き込みメソッドを呼び出す順序は重要です。理想的には、私がコードを書いた順序でドライバが書き込まれ、コードを書いた順序でドライバから読み取られるとよいでしょう。ただし、次のようにコードを記述した場合に気付きました...

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <signal.h>
#include <poll.h>

int main(void){
int num;
char *buff;
FILE *fd = fopen("/dev/hi","w");
num = fprintf(fd,"this is sentence 1 !!");
num = fprintf(fd,"this is sentence 2 !!");
num = fprintf(fd,"this is sentence 3 !!");
num = fprintf(fd,"this is sentence 4 !!");
num = fprintf(fd,"this is sentence 5 !!");
    close(fd);
    fd = fopen("/dev/hi","r");
buff = malloc(sizeof(char) * num+1);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
free(buff);
close(fd);
return 0;
}

fprintf() は、ファイル記述子を閉じたときにのみ書き込み、最悪の場合、デバイスから読み取った後に実行されることに気付きました。もちろん、私は自分のデバイスに書き込んでから読みたいと思っていますが、そのためには起こりません。これは、ユーザー空間の多くのことが同時に実行されているという印象を与え、私を困惑させます. ユーザー空間を処理するときにデバイス関数が呼び出される順序を知るにはどうすればよいですか? これが漠然としているように思われる場合は申し訳ありません。

返信ありがとうございます。

4

4 に答える 4

4

「fd」への書き込みはキャッシュされており、デバイスドライバーを閉じた後にのみ書き込まれます。これは正常であり、システム コールの数を減らすために行われます。

各書き込みをデバイスに送信する必要がある場合は、各書き込みの後に fsync() への呼び出しを追加してみてください。または、これは char ドライバであるため、行バッファリングされる可能性が最も高いため、各行の末尾に「\n」を追加してみてください。

于 2012-03-27T05:41:34.747 に答える
2

ユーザー空間のコードは順番に実行されます (並列処理または順序を混同するその他の概念で明示的に作業する場合を除きます)。

あなたが「暗い」と解釈するのは、fprintfのバッファリングに由来すると思われます。

fflush(fd)各 fprintf の後に呼び出すことで、バッファをフラッシュできます。また、事前に電話すると完全に無効にすることができますsetbuf(fd, NULL)

于 2012-03-27T05:42:42.907 に答える
1

fflushまたはfsyncを調べて、バッファリングされた出力をフラッシュし、読み取りを行う前に書き込みをコミットします。

于 2012-03-27T05:41:23.810 に答える
0

他の人が言ったように、それはバッファリングに関するものであり、奇妙な実行順序の影響ではありません。fflushを使用してストリームをフラッシュし、実際にデータを書き込むか、下位レベルのopenwriteなどの呼び出しを使用します。

しかし、私が指摘すべきだと思うもう一つのこと:

ストリームとファイル記述子について混乱しているようです。FILE*を「fd」と呼び、それがファイル記述子であると言います。しかし、FILE*はストリームであり、ファイル記述子ではありません。ファイル記述子は低レベルのものであり、stdio ライブラリによって隠されています。

Linux はopenを呼び出して取得するファイル記述子を提供し、 writeを使用してそのファイル記述子に書き込み、 close で閉じることができます。stdio ライブラリは、ファイル記述子の上に、独自の呼び出し ( fopenfwritefprintffcloseなど) と独自のバッファリングを備えた別のレベルを追加します。

また、ストリームを閉じるには、closeではなくfcloseを使用する必要があることに注意してください。

于 2012-03-27T06:04:18.483 に答える