现在我们就正式的进入linux下的c语言程序设计的学习了,学习linux下常用到的一些c函数。先来学习文件编程

linux下的文件编程就是实现对文件的一些操作,例如打开,读写什么的。这些c函数的调用不同于标准的c函数是因为我们学习的是系统的函数调用。系统调用就是unix/linux 定义的一系列的系统函数,用于进入内核空间,这些系统函数叫做系统调用。我们在标准c语言下使用的fopen()这个函数,其实是调用了不同系统的底层实现,让系统调用帮我们做事。fopen()->open()->软中断->sys_open(),这里边的open()函数就是系统调用,只不过是linux下的,我们在windows下使用fopen的时候调用的就是windows下的系统调用。

先来学习open系统调用,这个函数用来打开一个文件或者是设备,函数原型是:

int open(char *name,int flag,int mode)
name:文件的名字(带路径)就是你要打开哪个文件。
flags的值如下:
O_RDONLY只读 O_WRONLY只写 O_RDWR 读写,这三个值必选其一。
O_CREAT 如果文件不存在就创建它,存在的话就打开。
可以这样传入flag参数:O_WRONLY|O_CREAT 代表程序对它的权限是只写
注:如果是新创建文件需要第三个参数
mode:表示新创建文件的属性,这个代表的是创建的文件的属性,就是用户对它具有的一些权限,读用:r(4)写:w(2)执行:x(1)这里我们可以传入(O664)就代表前俩个用户对它具有读写的权限,第三个用户对它有只读的权限。

函数的返回值:文件描述符,用文件描述符代表一个打开的文件,文件的描述符本质就是一个非负整数。文件描述取值范围是0-OPEN(OPEN一般是256或1024)。0,1,2被操作系统预先占用,分别是标准输入,标准输出,标准错误

下面再来学习读写函数read和write。
int read(int fd,void *buf,size_t count)
int write(int fd,void *buf,size_t count)
参数:
fd:文件描述符
buf:任意类型的首地址
count:对于read期望值,对于write是实际值
返回值:真是字节数(读/写),错误返回-1,linux下的所有系统调用错误都会返回-1。

下面我们就通过这些函数实现一个文件拷贝的操作,代码如下。

#include <sys/types.h> //open函数的头文件
#include <sys/stat.h>  //open函数的头文件
#include <fcntl.h>  //open函数的头文件
#include <unistd.h> //unix/linux的标准库 read和write的头文件
#include <stdio.h>
#include <errno.h>  //目的是使用errno这个全局变量
#include <stdlib.h> //exit()的头文件

#define BUFFER_SIZE 1024

int main(int argc,char **argv)
{
	//源文件和目的文件的文件描述符
    int from_fd,to_fd;
    int bytes_read,bytes_write;
	//用来存放读取的数据
    char buffer[BUFFER_SIZE];
    char *ptr;
	//首先判断用户的输入是否合法argc是程序获得的参数个数,这些参数都保存在二维数组中。
    if(argc!=3)
    {
        fprintf(stderr,"Usage:%s fromfile tofile/n/a",argv[0]);
        exit(-1);
    }
    /* 打开源文件 */
    if((from_fd=open(argv[1],O_RDONLY))==-1)
    {
		//errno一个整数类型的全局变量,每次程序调用失败的时候,系统会自动用用错误代码填充errno这个全局变量
		//不同的整形数代表不同的意思,我们使用strerror()函数来为我们翻译出来,省得看一个整数。需要包含头文件errno.h
        fprintf(stderr,"Open %s Error:%s/n",argv[1],(char *)strerror(errno));
        exit(-1);
    }
    /* 创建目的文件 */
    if((to_fd=open(argv[2],O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))==-1)
    {
        fprintf(stderr,"Open %s Error:%s/n",argv[2],(char *)strerror(errno));
        exit(-1);
    }
    // 以下代码是一个经典的拷贝文件的代码
	//不断从输入文件中读取字符,如果返回值为0,代表没有读到字符也就是读取完毕,退出循环
    while(bytes_read=read(from_fd,buffer,BUFFER_SIZE))
    {
    //-1代表一个致命的错误发生了
        if((bytes_read==-1)&&(errno!=EINTR)) break;  //EINTR代表中断的系统调用
        else if(bytes_read>0)
        {
            ptr=buffer;
			//返回值代表实际写入的字符数,为0的时候代表已经写完了,注意第三个参数,读了多少字节就写多少字节
            while(bytes_write=write(to_fd,ptr,bytes_read))
            {
                /* 一个致命错误发生了 */
                if((bytes_write==-1)&&(errno!=EINTR))break;
                /* 写完了所有读的字节 */
                else if(bytes_write==bytes_read) break;
                /* 只写了一部分,继续写 */
                else if(bytes_write>0)
                {
					//ptr指向了没有写完的字符的开始处
                    ptr+=bytes_write;
					//bytes_read重新设为没有写完的字符数
                    bytes_read-=bytes_write;
                }
            }
            /* 写的时候发生了致命错误,就没有必要继续读了 */
            if(bytes_write==-1)break;
        }
    }
    close(from_fd);
    close(to_fd);
    exit(0);
}

linux下实现文件拷贝