Linux C语言函数API--系统I/O函数

一:系统I/O函数

1.open函数

【原型】    int open(const char *pathname,int flags);
           int open(const char *pathname,int flags,mode_t mode);
【功能】    打开一个指定的文件并获得文件描述符,或者创建一个新文件。
【头文件】    #include <sys/types.h>
            #include <sys/stat.h>
            #include <fcntl.h>
【参数flags】  O_RDONLY :只读方式打开文件
              O_WRONLY :只写方式打开文件
              O_RDWR   :读写方式打开文件
              O_CREAT  :如果文件不存在,则创建该文件
              O_EXCL   :如果使用O_CREAT选项且文件存在,则返回错误消息。
              O_NOCTTY :如果文件为终端,那么终端不可作为调用open()系统调用的那个进程的控制终端。
              O_TRUNC  :如果文件已经存在,则删除文件中原有数据。
              O_APPEND :以追加方式打开文件。
【参数mode】    如果文件被新建,指定其权限为mode(八进制表示法)
【返回值】 成功:返回>=0 的整数(即文件描述符)  失败 -1
【使用需要注意问题】
            1. flags 的各种取值可以用 位或 的方式叠加起来。
               比如:读写方式打开,不存在要新建,如果存在了则清空它 --->  O_RDWR | O_CREAT | O_TRUNC
            2.mode 是八进制权限,比如0644, 或者07553. open函数可以用来打开普通文件、块设备文件、字符设备文件、链接文件和管道文件
                但只能用来创建普通文件,每一种特殊文件的创建都有其特定的函数。
            4. 其返回值就是一个代表这个文件的描述符,是一个非负整数,这个整数将作为以后任何系统IO函数对其操作的句柄,或称入口。
代码演示:
-----------------------------------------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc,const **argv)
{
    int fd1,fd2,fd3,fd4,fd5;
    //在当前代码执行的目录中打开1.txt,2.txt,3.txt文件
    fd1 = open("./1.txt",O_RDONLY);             //只读模式打开
    fd2 = open("./2.txt",O_RDWR|O_CREAT);       //读写打开,没有则创建
    fd3 = open("./3.txt",O_RDWR|O_CREAT|O_EXCL);//读写模式打开,没有则创建,如果有,则返回错误值
    fd4 = open("./1.txt",O_WRONLY);             //只写模式打开
    fd5 = open("./1.txt",O_RDONLY);             //还是以只读模式打开
    
    printf("%d\n",fd1);     //3
    printf("%d\n",fd2);     //4
    printf("%d\n",fd3);     //-1
    printf("%d\n",fd4);     //5
    printf("%d\n",fd5);     //6
    return 0;
}
-----------------------------------------------------------------------------------------------------------------------

2.close函数

【原型  】   int close(int fd);  
【功能  】  关闭文件并释放相应的资源。
【头文件】  #include<unistd.h>
【参数fd】  即将要关闭的文件描述符
【返回值】 成功 0 失败 -1
【备注】    重复关闭一个已经关闭了的文件或者尚未打开的文件是安全的。
代码演示:
-----------------------------------------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>         //close函数所在的头文件
int main(int argc,const **argv)
{
    int fd1,fd2,n1,n2,n3;
    //在当前代码执行的目录中打开1.txt,2.txt以及关闭这两个文件
    fd1 = open("./1.txt",O_RDONLY);             //只读模式打开
    fd2 = open("./2.txt",O_RDWR|O_CREAT);       //读写打开,没有则创建
    printf("%d\n",fd1);     //3
    printf("%d\n",fd2);     //4

    n1 = close(3);
    n2 = close(4);
    n3 = close(20);     //关闭不存在的文件描述符
    
    printf("%d\n",n1);      //0  -->成功
    printf("%d\n",n2);      //0  -->成功
    printf("%d\n",n3);      //-1 -->失败
    
    return 0;
}
-----------------------------------------------------------------------------------------------------------------------

3.read函数

【原型】    ssize_t read(int fd void *buf,size_t count);
【功能】    从指定文件中读取数据
【头文件】   #include <unistd.h>
【参数fd】  从文件fd中读取数据
【参数buf】 指向存放读读取的字节数
【参数count】想要从文件fd中读取的字节数
【返回值】 成功:实际读到的字节数  失败 -1

【备注】    实际读到的字节数小于count

代码演示:
-----------------------------------------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>         //close函数所在的头文件
int main(int argc,const **argv)
{
    int fd1,n1,i;
    char buf[100];
    fd1 = open("./1.txt",O_RDONLY);             //只读模式打开
    
    printf("%d\n",fd1);     //3
    n1=read(3,buf,100);     //向文件描述符为3的文件里面读取100个字节,并且将读取的字节数赋值给n1
    printf("%d\n",n1);
    
    return 0;
}
-----------------------------------------------------------------------------------------------------------------------

4.write函数

【原型】    ssize_t write(int fd,const void *buf,size_t count);
【功能】    将数据写入指定的文件
【头文件】 #include <unistd.h>

【参数fd】  将数据写入到文件fd中
【参数buf】 指向即将要写入的数据
【参数count】要写入的字节数
【返回】    成功:实际写入的字节数   失败:-1
【备注】    实际写入的字节数小于等于count
【注意】
            1. 实际读写的字节数要通过返回值来判断,参数count只是一个"愿望值";
            2. 当实际的读写字节数小于count 时,有以下几种情形:
                A)读操作时,文件剩余可读字节数不足count
                B)读写操作期间,进程收到异步信号
            3. 读写操作同时对f_pos起作用。也就是说,不管是读还是写,文件的位置偏移量(即内核中的f_pos)都会
                加上实际读写的字节数,不断的往后偏移。

代码演示:

-----------------------------------------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>         //write函数所在头文件
int main(int argc,const **argv)
{
    int fd1,n1;
    char buf[20]="abacfjd";
    fd1 = open("./2.txt",O_WRONLY);             //读写模式打开
    
    printf("%d\n",fd1);     //3
    n1=write(3,buf,20);     //向文件描述符为3的文件里面读取20个字节,并且将读取的字节数赋值给n1
    printf("%d\n",n1);          
    
    return 0;
}
-----------------------------------------------------------------------------------------------------------------------

5.lseek函数


【原型】    off_lseek(int fd,off_t offset, int whence);
【功能】调整文件位置偏移量
【头文件】	#include <sys/types.h>,#include <unistd.h>
【参数fd】  要调整位置偏移量的文件的描述符。
【参数offset】 新位置偏移量相对基准点
【参数whence】基准点:SEEK_SET:文件开头处
                      SEEK_CUR:当前位置
                      SEEK_END:文件末尾处
【返回值】 成功: 新文件位置偏移量  失败 -1

【注意要点】
            1.lseek() 只对普通文件奏效,特殊文件时无法调整偏移量的。
  

代码演示:
-----------------------------------------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>         //write函数所在头文件
int main(int argc,const **argv)
{
    int fd;         //文件描述符

    fd = open("./2.txt",O_RDWR);
    
    printf("%d\n",fd);      //3
    /*------第1次执行,//往空白文件2.txt写入数据,执行完毕加上// ---- 
    
    write(fd,"123456789",9);     
    /*---------------------------------------*/
    
    /*----第2次执行,执行完毕加上//
    lseek(fd,0,SEEK_SET);       //相对于首位基准点往后移动0个字节后写入
    write(fd,"a",1);            //写入a
    //--此时变成:a23456789   覆盖了1
    
    -------------------------------------*/
    
    lseek(fd,-1,SEEK_SET);      //相对于首位基准点往后移动-1个字节后写入
    write(fd,"1",1);            //写入1
    
    //结果为:123456789
    
    //lseek(fd,3,SEEK_SET);     //相对于首位基准点往后移动3个字节后写入
    //write(fd,"b",1);          //写入b
    
    //lseek(fd,2,SEEK_CUR);     //相对于中心基准点往后移动2个字节开始写入
    //write(fd,"c",1);
    
    //lseek(fd,2,SEEK_END);     //相对于尾部基准点往后移动2个字节开始写入
    //write(fd,"d",1);
    //close(fd);
    return 0;
}
-----------------------------------------------------------------------------------------------------------------------

6.dup函数

【原型】    int dup(int oldfd);

【功能】    复制文件描述符
【头文件】 #include<unistd.h>
【参数oldfd】要复制的文件描述符
【返回值】 成功:新的文件描述符   失败 -1

7.dup2函数

【原型】    int dup2(int oldfd,int newfd);
【功能】    复制文件描述符
【头文件】 #include<unistd.h>
【参数oldfd】   要复制的文件描述符
【参数newfd】   指定的新文件描述符
【返回值】 成功:新文件描述符  失败 -1


代码演示:
-----------------------------------------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>         //write函数所在头文件
int main(int argc,const **argv)
{
    int fd,newfd,newfd1;            //文件描述符

    fd = open("./2.txt",O_RDWR);
    
    printf("%d\n",fd);      //3
    
    newfd = dup(3);
    printf("%d\n",newfd);   //4
    
    newfd1 = dup2(3,100);
    printf("%d\n",newfd1);  //100
    
    //此时文件2.txt有多个描述符可以指向它。3,4,100
    write(3,"222222",6);
    
    return 0;
}


-----------------------------------------------------------------------------------------------------------------------

8.ioctl函数

【原型】    int ioctl(int d,int request,...);
【功能】    文件控制
【头文件】 #include <sys/ioctl.h>
【参数d】   要控制的文件描述符
【参数request】 针对不同文件的各种控制命令字
【变参】    根据不同的命令而不同
【返回值】 成功:一般情况下是0,但有些特定的请求将返回非负整数。  失败 -1

9.fcntl函数

【原型】    int fcntl(int fd,int cmd,.../*arg*/);
【功能】    文件控制
【头文件】 #include<unistd.h>,#include <fcntl.h>
【参数fd】  要控制的文件描述符
【参数cmd】 控制命令字
【变参】    根据不同的命令而不同。

【返回值】 成功: 根据不同的cmd ,返回值不同。 失败  -1

10.mmap函数

【原型】    void *mmap(void *addr,size_t length,int prot,int flags, int fd,off_t offset);
【功能】    内存映射
【头文件】 #include <sys/mman.h>
【参数addr】        映射内存的起始地址。
                 如果该参数为NULL,则系统会自动寻找一个合适的起始地址,一般都使用这个值。
                 如果该参数不为NULL,则系统会以此为依据来找到一个合适的起始地址,在Linux中,映射后的内存起始地址必须是页地址的整数倍。
【参数length】  映射内存大小。
【参数prot】    映射内存的保护权限。PROT_EXEC :可执行
                                    PROT_READ :可读。
                                    PROT_WRITE :可写
                                    PROT_NONE :不可访问。

【参数flag】    以下两个选项互斥:
                    1.MAP_SHARED:所有的同时映射了这块内存的进程对数据的变更均可见,而且数据的变更会直接同步到对应的文件
                        有时可能还需要调用mync()或者munmap()才会真正起作用。
                    2.MAP_PRIVATE :与MAP_SHARED相反,映射了这块内存的进程对数据的变更对别的进程不可见,也不会影响其对应的文件数据。
                
                以下选项可以位或累加:
                    1.MAP_32BIT :在早期的64位x86处理器上,设置这个选项可以将线程的栈空间设置在最低的2GB空间附近
                    2.MAP_ANONYMOUS :匿名映射,该选项使得该映射内存不与任何文件关联,一般来讲参数fd和offset会被忽略(但是可移植性程序需要
                        将fd设置为-1),另外,这个选项必须跟MAP_SHARED 一起使用。
                        
                    3.MAP_DENYWRITE :很久以前,这个选项可以使得试图写文件fd的进程收到一个ETXTBUSY的错误
但是这很快成为所谓"拒绝服务"攻击的来源。
                    4.MAP_FIXED :该选项使得映射内存的起始地址严格等于参数addr而由于可移植性的关系,这个选项一般不建议设置。
                    5.MAP_GROWSDOWN :使得映射内存向下增长,即返回的是内存的最高地址,一般用于栈。
                    6.MAP_HUGETLB:使用"大页"来分配映射内存,关于"大页",请参考内核源代码中的Documentation/vm/hugetlbpage.txt.
                    7.MAP_NONBLOCK :该选项必须与MAP_POPULATE 一起使用,表示不进行"预读"操作,这使得选项MAP_POPULATE变得毫无意义。
                    8.MAP_NORESERVE: 该选项是不为这块内存使用“交换分区”,也就是说当物理内存不足时,操作映射内存将会受到SIGSEGV,
而如果允许使用交换分区则可以保证不会因为物理内存不足而出现这个错误。
                    9.MAP_POPULATE: 将页表映射至内存中,如果用于文件映射,该选项会导致预读的操作,因而在遇到页错误的时候也不会被阻塞。
                    10.MAP——STACK :在进程或线程的栈中映射内存。
                    11.MAP_UNINITIALIZED :不初始化匿名映射内存。
                    
【参数fd】  要映射的文件的描述符

【参数offset】文件映射的开始区域偏移量,该值必须是页内存大小的整数倍,即必须是函数sysconf(_SC_PAGE_SIZE)返回的整数倍。

【返回值】     成功: 映射内存的起始地址。  失败 (void*) -1;

11. memcpy函数

【原型】    void *memcpy(void *dest, const void *src , size_t n);
【功能】    从src地址指向的数据上拷贝n个字节到目标地址dest指向的空间上
【头文件】 #include <string.h>
【参数】    dest:目标地址
            src:原有数据的地址
            n:拷贝的字节数
【返回值】成功:指向目标地址上基地址的指针 失败:NULL


代码演示:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>       //mmap函数所在头文件
#include <string.h>         //memcpy函数所在头文件
int main(int argc,const **argv)
{ 
 int lcd = open("/dev/fb0",O_RDWR); //以读写的方式打开lce液晶显示屏
    
    if(lcd < 0)  
    {    
        printf("open lcd error!\n");  
        return 0;
    }
    //2.内存映射
    
    int *FB = NULL;
    FB = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd,0);
        //自动寻找起始地址,映射出800*480*4个字节的地址,可读,可写,
        //所有的同时映射了这块内存的进程对数据的变更均可见,而且数据
        //的变更会直接同步到对应的文件
        //lcd:要映射的文件描述符   0:代表文件映射的开始区域偏移量
    
    
    //3.数据拷贝
    
    int color = 0x00FF0000;     //颜色是16位
    
    int i;
    
    for(i=0;i<800*480;i++)
    
    {     
        memcpy(FB+i,&color,4);
        //每个地址是4个字节,将clolor数据的地址每次拷贝4个字节数
    }
    //4.撤销内存映射和关闭文件,
    
    munmap(FB,800*480*4);           //撤销内存映射和关闭文件
    close(lcd);
    return 0;
}



系统I/O函数部分功能的实现:


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

/*========================
    函数功能:判断文件类型
    创建者:yeyonghong
=========================*/
/*
    描述:
    0.参数:argv为当前所输入的名字  返回值:为各个文件类型的简写
    1.结构体struct stat是系统自定义
    2.宏:系统已定义
    3.此函数可判断的文件类型有:
            普通文件、目录、字符设备文件、块设备文件
            管道文件、链接文件、套接字文件
    4.此处只是提供了判断其中四种的。
    5.字符设备:CHR、块设备:BLK、套接字:SOCK
**/
char *FileType(char *argv)
{
    //1.定义一个stat结构体info,用来存放指定文件属性
    struct stat info;
    //2.将这个文件放入到info里面进行判断
    stat(argv,&info);
    if(S_ISDIR(info.st_mode))
    {
        printf("这是一个目录!\n");
        return "DIR";
    }
    else if(S_ISREG(info.st_mode))
    {
        printf("这是一个普通文件!\n");
        return "REG";
    }
    else if(S_ISFIFO(info.st_mode))
    {
        printf("这是一个管道文件!\n");
        return "FIFO";
    }
    else if(S_ISLNK(info.st_mode))
    {
        printf("这是一个链接文件!\n");
        return "LNK";
    }
    
}

/*=================
    功能2:打开目录
 ==================*/
 /*
    0.参数:argv:目录指针
    1.内部函数:opendir(),readdir(),chidir(),system();
    2.内部结构体:
        struct dirent
        {
            ino_t d_ino;            //文件索引号
            off_t d_off;            //目录项偏移量
            unsigned short d_reclen; //该目录项大小
            unsigned char d_type;   //文件类型
            char d_name[256];       //文件名
        };
    
 **/
char *Dir(char *argv)
{
    //1.获取指定目录指针
    DIR *dp = opendir(argv);    
    struct dirent *ep = NULL;
    //2.读取目录项指针,每读取一次指针自动后移一位,直到为NULL
    while(1)
    {
        ep = readdir(dp);               
        if(ep == NULL)
            break;
        printf("%d :",(int)ep->d_off);    //文件偏移量
        printf("%s\n",ep->d_name);      //打印文件名
    }
    //3.重置目录流指针,将目录指针还原初始值
    rewinddir(dp);  
    //4.切换到当前路径   
    chdir(argv);
    //5.显示当前工作路径    
    system("pwd");                      
    return NULL;
}

/*==============
    功能3:读取文件
 ===============*/
 /*
    0.参数:argv:文件描述符、buf:数据缓冲区、size:读取字节数大小
    1.所用到的内部函数:open()、read()、close()
    2.返回值:字符串
 **/
char *Read(char *argv,char *buf,int size)
{
    int fd = open(argv,O_RDWR);
    printf("%s\n",argv);
    read(fd,buf,size);
    printf("%s\n",buf);
    close(fd);
    return NULL;
}


/*==========
    功能4:向文件写入数据
=============*/
/*
    0.参数:argv:文件描述符、buf:数据缓冲区、size:写入字节数大小
    1.所用到的内部函数:open()、write()、close()
    2.返回值:字符串
**/
char *Write(char *argv,char *buf,int size)
{
    int fd = open(argv,O_RDWR);
    printf("%s\n",argv);
    write(fd,buf,size);
    close(fd);
    return NULL;
}


int main(int argc,char **argv)
{
    char arg[20] = {0};
    char ch2[20] = {0};
    char buf1[100]={0};
    char *buf2="abcdefghijklmn";
    while(1)
    {
        printf("请输入要查找的目录: ");
        scanf("%s",arg);
        char *arg1 = FileType(arg);
        
        if(strcmp(arg1,"DIR")==0)
        {
            Dir(arg);
        }
        if(strcmp(arg1,"REG")==0)
        {
            Read(arg,buf1,100);
            Write(arg,buf2,sizeof(buf2));
        }
    }
    return 0;
}




发布了9 篇原创文章 · 获赞 10 · 访问量 283

猜你喜欢

转载自blog.csdn.net/my___sunshine/article/details/103999343
今日推荐