linux c cp程序实现

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

#define BUFFERSIZE 4096
#define COPYMODE 0644

void oops(char *, char *);

main(int ac, char *av[]) {
	int in_fd, out_fd, n_chars;
	char buf[BUFFERSIZE];

	if (ac !=3) {
		fprintf(stderr, "usage: %s source destination\n", *av);
		exit(1);
	}

	if ((in_fd = open(av[1], O_RDONLY)) == -1) {
		oops("Cannot open", av[1]);
	}

	if ((out_fd = creat(av[2], COPYMODE)) == -1) {
		oops("Cannot creat", av[2]);
	}

	while((n_chars = read(in_fd, buf, BUFFERSIZE)) > 0) {
		if (write(out_fd, buf, n_chars) != n_chars) {
			oops("Write error to", av[2]);
		}
	}

	if (n_chars == -1) {
		oops("Read error from", av[1]);
	}

	if (close(in_fd) == -1 || close(out_fd) == -1) {
		oops("Error closing files", "");
	}

}

void oops(char *s1, char * s2) {
	fprintf(stderr, "Error: %s ", s1);
	perror(s2);
	exit(1);
}
$ cc cp1.c -o cp1
$ cp1 src dest

总结:

创建/重写文件,如果文件不存在,就创建它,存在,就把它的内容清空,把文件的长度设为0
creat
作用:创建/重写一个文件
头文件:fcntl.h
原型:int fd = creat(char *filename, mode_t mode)
参数:filename 文件名,mode 访问模式
返回值:-1 遇到错误,fd成功创建

写文件:用write调用向已打开的文件中写入数据,如果写入失败,返回-1, 如果写入成功,返回写入的字节数
write
目标:将内存中的数据写入文件
函数原型:ssize_t result = write(int fd, void *buf, size_t amt)
参数:fd 文件描述符;buf 内存数据,amt 要写的字节数
返回值:-1 遇到错误;num written 成功写入

读文件:由已打开的文件读数据,返回值为实际读取到的字节数,如果返回0,表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动。目的会把参数fd所指的文件传送count个字节到buf指针所指的内存中
read
头文件:unistd.h
函数原型: ssize_t read(int fd,void * buf ,size_t count); 
参数:fd 文件描述符,buf 读取的内容存放处, count 读取的字节数

main
int argc (传递的参数个数,文件名也算是一个)
char *argv[] 传递的参数值

为什么系统调用需要很多时间?

用户进程位于用户空间,内核位于系统空间,磁盘只能被内核直接访问。上述程序cp1要读取磁盘上的数据只能通过系统调用read,而read代码在内核中,所以当read调用发生时,执行权会从用户代码转移到内核代码,执行内核代码是需要时间的。

系统调用的开销大不仅仅是因为要传输数据,当运行内核代码时,cpu工作在管理员模式,这对应于一些特殊的堆栈和内存环境,必须在系统调用 发生时建立好。系统调用结束后(read返回时),cpu又要切换到用户模式,必须把堆栈和内存环境恢复到用户程序运行的状态,这种运行环境的切换要消耗很多时间。

当工作在管理员模式下,程序可以直接访问磁盘,终端,打印机等设备,还可以访问全部的内存空间,而用户模式,程序不能直接访问设备,也只能访问特定部分的内存空间。在运行时刻,系统会根据需要不断地在两种模式间切换。管理员模式和用户模式的切换与cpu关系很大,cpu中特定的标记来区分当前的工作模式,而unix系统的设计必须考虑到cpu的这种特点,才能实现不同工作模式间的良好切换。

在计算机的世界中也是一样,要是cpu把太多的时间消耗在执行内核代码和模式切换上,就不可能有很多时间来执行程序中业务逻辑的代码或提供系统服务,所以要尽可能地减少模式间的切换,对于系统来说,这种时间上的开销是昂贵的。