4

私の OS クラスでは、Unix の cat コマンドをシステム コール (scanf または printf なし) で実装する割り当てがあります。これが私がこれまでに得たものです:

(回答のおかげで編集されました)

#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>



main(void)
{


   int fd1; 
   int fd2;

   char *buffer1;
   buffer1 = (char *) calloc(100, sizeof(char));


   char *buffer2;
   buffer2 = (char *)calloc(100, sizeof(char));

   fd1 = open("input.in", O_RDONLY);    
   fd2 = open("input2.in", O_RDONLY);


   while(eof1){ //<-lseek condition to add here
   read (fd1, buffer1, /*how much to read here?*/ );
   write(1, buffer1, sizeof(buffer1)-1);     
   }


   while (eof2){ 

    read (fd2,buffer2, /*how much to read here?*/);  
    write(1, buffer2, sizeof(buffer2)-1);

    }

}

私が見た例は、既知のバイト数での読み取りのみを示しています。各読み取りファイルのバイト数がわからないので、読み取りの最後のパラメーターを指定するにはどうすればよいですか?

4

5 に答える 5

4
  • バッファに入れる前readに、バッファを割り当てる必要があります。スタック上(最も簡単)またはmmap
  • perrorは複雑なライブラリ関数であり、システムコールではありません。
  • exitLinuxではシステムコールではありません。しかし、そう_exitです。
  • write以前より多くのバイトを使用しないでくださいread
  • または、一般的に:これらすべてのシステムコールに関するドキュメントをお読みください。

編集:これが私のコードで、システムコールのみを使用しています。再実装したくなかったので、エラー処理は多少制限されていperrorます。

#include <fcntl.h>
#include <unistd.h>

static int
cat_fd(int fd) {
  char buf[4096];
  ssize_t nread;

  while ((nread = read(fd, buf, sizeof buf)) > 0) {
    ssize_t ntotalwritten = 0;
    while (ntotalwritten < nread) {
      ssize_t nwritten = write(STDOUT_FILENO, buf + ntotalwritten, nread - ntotalwritten);
      if (nwritten < 1)
        return -1;
      ntotalwritten += nwritten;
    }
  }

  return nread == 0 ? 0 : -1;
}

static int
cat(const char *fname) {
  int fd, success;

  if ((fd = open(fname, O_RDONLY)) == -1)
    return -1;

  success = cat_fd(fd);

  if (close(fd) != 0)
    return -1;

  return success;
}


int
main(int argc, char **argv) {
  int i;

  if (argc == 1) {
    if (cat_fd(STDIN_FILENO) != 0)
      goto error;
  } else {
    for (i = 1; i < argc; i++) {
      if (cat(argv[i]) != 0)
        goto error;
    }
  }
  return 0;

error:
  write(STDOUT_FILENO, "error\n", 6);
  return 1;
}
于 2010-10-05T18:18:17.107 に答える
3

バッファに収まるだけのバイトを読み取る必要があります。現在、バッファはまだありません。取得したのはバッファへのポインタだけです。それは何にも初期化されていません。したがって、鶏が先か卵が先か、何バイトを読み取るかがわかりません。

バッファを作成します。

于 2010-10-05T18:18:19.163 に答える
2

openfstatmmapmadviseおよびwriteを使用して、非常に効率的な cat コマンドを作成できます。

Linux 固有の場合は、、、およびを使用してopen、より効率的な cat コマンドを作成できます。fstatfadvisesplice

アドバイス呼び出しは、ファイルに対して積極的な先読みを行うようにカーネルに指示する SEQUENTIAL フラグを指定することです。

システムの残りの部分に礼儀正しく、バッファ キャッシュの使用を最小限に抑えたい場合は、コピーを 32 メガバイト程度のチャンクで行い、既に読み取った部分にアドバイス DONTNEED フラグを使用できます。

ノート:

上記は、ソースがファイルの場合にのみ機能します。fstat がサイズを提供できない場合は、割り当てられたバッファreadwrite. あなたも使うことができますsplice

于 2010-10-05T19:13:22.110 に答える
2

通常、ファイル全体を一気に読む必要はありません。ホスト オペレーティング システムのメモリ ページ サイズと同じか、その倍数のバッファー サイズを選択することをお勧めします。おそらく、ページ サイズの 1 倍または 2 倍で十分です。

大きすぎるバッファを使用すると、仮想メモリ システムに圧力がかかり、ページングが発生する可能性があるため、実際にはプログラムの実行が悪化する可能性があります。

于 2010-10-05T18:48:34.060 に答える
1

stat関数を使用して、ファイルを読み取る前にファイルのサイズを確認してください。または、EOFを取得するまでチャンクを読み取ることもできます。

于 2010-10-05T18:16:24.887 に答える