readとwrite関数の使用
3644 ワード
ヘッダファイルを含める必要があります.
readシステム関数は、開いたデバイスまたはファイルからデータを読み出し、外付けデバイスからカーネルを介してユーザ空間にデータを読み出す.writeシステム関数は逆に、開いているデバイスやファイルにデータを書き込み、ユーザースペース(I/Oバッファ)からカーネルにデータを送り、外付けデバイスにブラシをかけます.これらの関数のプロトタイプは次のとおりです.
ssize_t read(int fd, void *buf, size_t count);
ssize_tは符号付き整数、size_tは符号なし整数である.fdは対応するファイル記述子である.bufは、固定サイズではなくcount値によってそのサイズ(ユーザが与えたバイト数)を決定するユーザに与えられたデータバッファである.例えばread(fd,“hello”,5);このときのvoid*bufはchar*タイプです.すなわちcountは、読み出しを要求するバイト数(すなわちbufのサイズ)である.この関数の戻り値が-1の場合、データの読み取りに失敗したことを示します.戻り値>0の場合、読み出したバイト数を示す.戻り値が0に等しい場合は、読み終わったのでデータが読めないことを示します.
ssize_t write(int fd, const void *buf, size_t count);
bufは、出力が必要なバッファであり、ユーザによって与えられる.coutは最大出力バイト数(bufのサイズ、バイト数)である.戻り値が-1の場合、書き込みに失敗しました.>=0の場合、書き込みバイト数を表します.
以上の2つのバッファbufはいずれもユーザ空間のアドレスであるが、I/Oバッファとは異なり後者は所定であり、前者はユーザ自身が指定したものである.
思考:read、writeを利用して1つのByteを読むか書くか、getsとputsを利用して1つのByteを読むか書くか、どちらが速いですか.
readおよびwrite関数はLinuxシステム関数であり、そのバッファはユーザによって維持される.すなわち、ユーザがそのサイズを指定し、ユーザ空間のデータを毎回カーネルに送るか、カーネルからユーザ空間に送るデータのサイズはユーザによって規定される.一方、getsとputsはCライブラリ関数であり、そのI/Oバッファはライブラリ関数によって自分で維持され、サイズは8 Byteであるため、平均的に8つのByteを転送するデータ量ごとにカーネルが操作される.以上のように、データを読み書きする場合、read、write関数は、ユーザ空間から1 byteデータを読み出すたびにカーネル(システム呼び出し)を操作します(オーバーヘッドが大きく、速度が遅くなります.putsとgets関数は高速です.もちろん、readとwriteのcountパラメータを指定してバッファサイズを大きくし、putsとgetsよりも高速に読み書きできます.(大きなファイルでは、より効果的です).
readとwriteの使い方を例に挙げて説明します.
//あるファイル(english.txt)の内容を別のファイル(writefile.txt)に読み込む
[root@localhost work]# vim rdwr.c
[root@localhost work]# ls
english.txt rdwr.c
[root@localhost work]# gcc -pipe -pedantic -Wall -ggdb3 rdwr.c -o rdwr
[root@localhost work]# ./rdwr
open readfile's fd=3
read readfile's fd1=1024
open writefile's fd2=4
[root@localhost work]# ls
english.txt rdwr rdwr.c writefile.txt
[root@localhost work]# ll writefile.txt
-rwxrwxrwx. 1 root root 109055 Mar 19 11:39 writefile.txt
[root@localhost work]# ll english.txt
-rwxrwxrwx. 1 root root 109055 Mar 19 10:30 english.txt//ファイルサイズが同じ
readシステム関数は、開いたデバイスまたはファイルからデータを読み出し、外付けデバイスからカーネルを介してユーザ空間にデータを読み出す.writeシステム関数は逆に、開いているデバイスやファイルにデータを書き込み、ユーザースペース(I/Oバッファ)からカーネルにデータを送り、外付けデバイスにブラシをかけます.これらの関数のプロトタイプは次のとおりです.
ssize_t read(int fd, void *buf, size_t count);
ssize_tは符号付き整数、size_tは符号なし整数である.fdは対応するファイル記述子である.bufは、固定サイズではなくcount値によってそのサイズ(ユーザが与えたバイト数)を決定するユーザに与えられたデータバッファである.例えばread(fd,“hello”,5);このときのvoid*bufはchar*タイプです.すなわちcountは、読み出しを要求するバイト数(すなわちbufのサイズ)である.この関数の戻り値が-1の場合、データの読み取りに失敗したことを示します.戻り値>0の場合、読み出したバイト数を示す.戻り値が0に等しい場合は、読み終わったのでデータが読めないことを示します.
ssize_t write(int fd, const void *buf, size_t count);
bufは、出力が必要なバッファであり、ユーザによって与えられる.coutは最大出力バイト数(bufのサイズ、バイト数)である.戻り値が-1の場合、書き込みに失敗しました.>=0の場合、書き込みバイト数を表します.
以上の2つのバッファbufはいずれもユーザ空間のアドレスであるが、I/Oバッファとは異なり後者は所定であり、前者はユーザ自身が指定したものである.
思考:read、writeを利用して1つのByteを読むか書くか、getsとputsを利用して1つのByteを読むか書くか、どちらが速いですか.
readおよびwrite関数はLinuxシステム関数であり、そのバッファはユーザによって維持される.すなわち、ユーザがそのサイズを指定し、ユーザ空間のデータを毎回カーネルに送るか、カーネルからユーザ空間に送るデータのサイズはユーザによって規定される.一方、getsとputsはCライブラリ関数であり、そのI/Oバッファはライブラリ関数によって自分で維持され、サイズは8 Byteであるため、平均的に8つのByteを転送するデータ量ごとにカーネルが操作される.以上のように、データを読み書きする場合、read、write関数は、ユーザ空間から1 byteデータを読み出すたびにカーネル(システム呼び出し)を操作します(オーバーヘッドが大きく、速度が遅くなります.putsとgets関数は高速です.もちろん、readとwriteのcountパラメータを指定してバッファサイズを大きくし、putsとgetsよりも高速に読み書きできます.(大きなファイルでは、より効果的です).
readとwriteの使い方を例に挙げて説明します.
//あるファイル(english.txt)の内容を別のファイル(writefile.txt)に読み込む
[root@localhost work]# vim rdwr.c
[root@localhost work]# ls
english.txt rdwr.c
#include
#include
#include
#include
#include
#include
int main( )
{
int fd;
fd = open("english.txt",O_RDONLY); //
printf("open readfile's fd=%d
",fd);
if( fd == -1 )
{
perror(" open english.txt " );
exit(1);
}
int fd1;
char buff[1024] = { 0 }; //
fd1 = read( fd,buff,sizeof(buff) ); //
printf("read readfile's fd1=%d
",fd1);
if( fd1 == -1 )
{
perror(" read english.txt " );
exit(1);
}
int fd2;
fd2 = open( "writefile.txt" ,O_WRONLY | O_CREAT | O_EXCL,0664); // , , ,
printf("open writefile's fd2=%d
",fd2);
if ( fd2 == -1 )
{
perror( "creat file" );
exit(1);
}
int ret;
while( fd1 )
{
ret = write( fd2,buff,fd1); //
if( ret == -1 )
{
perror( "write file");
exit(1);
}
fd1 = read( fd,buff,1024); //
if( fd1 == -1 )
{
perror(" read english.txt " );
exit(1);
}
}
int qw1;
int qw2;
qw1=close(fd); //
if( ret == -1 )
{
perror( "close readfile");
exit(1);
}
qw2=close(fd2);
if( ret == -1 )
{
perror( "close writefile");
exit(1);
}
return 0;
}
[root@localhost work]# gcc -pipe -pedantic -Wall -ggdb3 rdwr.c -o rdwr
[root@localhost work]# ./rdwr
open readfile's fd=3
read readfile's fd1=1024
open writefile's fd2=4
[root@localhost work]# ls
english.txt rdwr rdwr.c writefile.txt
[root@localhost work]# ll writefile.txt
-rwxrwxrwx. 1 root root 109055 Mar 19 11:39 writefile.txt
[root@localhost work]# ll english.txt
-rwxrwxrwx. 1 root root 109055 Mar 19 10:30 english.txt//ファイルサイズが同じ