以文件拷贝为例:
We’ll do this in a number of ways during this chapter to compare the efficiency of each method. For brevity, we’ll assume that the input file exists and the output file does not, and that all reads and writes succeed. Of course, in real-life programs, we would check that these assumptions are valid!
#include
#include
#include
#include
int main()
{
char c;
int in, out;
in = open(“file.in”, O_RDONLY);
out = open(“file.out”, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
while(read(in,&c,1) == 1)
write(out,&c,1);
exit(0);
}
First, we will need to make a test input file, say 1 Mb in size, and name it file.in.
Running the program will give something like the following:
$ TIMEFORMAT=”” time copy_system
4.67user 146.90system 2:32.57elapsed 99%CPU
...
$ ls -ls file.in file.out
1029 -rw-r—-r- 1 neil users 1048576 Sep 17 10:46 file.in
1029 -rw———- 1 neil users 1048576 Sep 17 10:51 file.out
Here we use the timefacility to measure how long the program takes to run. The TIMEFORMAT vari-able is used on Linux to override the default POSIX output format of time, which does not include the CPU usage. We can see that for this fairly old system, the 1-Mb input file, file.in, was successfully copied to file.out, which was created with read/write permissions for owner only. However, the copy took two-and-a-half minutes and consumed virtually all the CPU time. It was this slow because it had to make over 2 million system calls.
In recent years, Linux has seen great strides in its system call and file system performance. By compari-son, a similar test using a 2.4 kernel completed in a little under 5 seconds.
$ TIMEFORMAT=”” time copy_system
1.07user 3.50system 0:04.77elapsed 95%CPU
...
We can improve matters by copying in larger blocks. Take a look at this modified program,copy_block.c, which copies the files in 1k blocks, again using system calls:
#include
#include
#include
#include
int main()
{
char block[1024];
int in, out;
int nread;
in = open(“file.in”, O_RDONLY);
out = open(“file.out”, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
while((nread = read(in,block,sizeof(block))) > 0)
write(out,block,nread);
exit(0);
}
Now try the program, first removing the old output file:
$ rm file.out
$ TIMEFORMAT=”” time copy_block
0.00user 0.01system 0:00.01elapsed 62%CPU
...
Now the program takes a hundredth of a second, as it requires only around 2,000 system calls. Of
course, these times are very system-dependent, but they do show that system calls have a measurable
overhead, so it’s worth optimizing their use.