技术交流 QQ 群:1027579432,欢迎你的加入!

欢迎关注我的微信公众号:CurryCoder的程序人生

1.标准C库IO函数工作流程

  • IO缓冲区的作用?

    • 大部分硬盘都是机械硬盘,读取寻道时间和写入寻道时间都是在毫秒级ms;
    • 相对来说,内存读写速度都非常块,因为内存属于电子设备,读写速度是纳秒级ns;
    • 两者之间的读写速度相差一百万倍;

2.标准C库函数与Linux系统函数之间的关系


3.虚拟地址空间

  • 程序运行以后,首先,每个进程都会创建各自独立的虚拟地址空间。接着,CPU执行代码时(实质是CPU中的MMU将虚拟地址空间中的数据映射到物理内存中,然后在物理内存中进行数据处理),其实是在物理内存中进行数据处理的。
  • 虚拟地址空间的优点:在虚拟地址空间中的堆空间中申请了20M堆空间。为了能在物理内存中进行数据处理,需要将虚拟地址空间中的数据映射到物理内存中。但是,物理内存中没有连续的20M内存空间。然而,使用了这种映射机制后,可以将物理内存中不连续的20M内存空间连接到一起。例如:C++的STL中的vector内存地址是连续的,但是deque的内存地址是不连续的,却可以通过映射机制能够保证内存地址是连续的。

4.文件描述符表

  • 标准输入stdin文件描述符0、标准输出stdout文件描述符1、标准错误stderr文件描述符2。
  • 文件描述符的作用:通过文件描述符来寻找对应的磁盘文件。
  • 进程控制块pcb:本质就是一个结构体。
  • 一个进程有一个文件描述符表,前三个默认被占用了。

5.Linux系统文件IO函数

  • open函数原型:

    • int open(const char *pathname, int flags);
    • int open(const char *pathname, int flags, mode_t mode);
  • 参数:
    • flags参数为一个32位整数:必选参数O_RDONLY, O_WRONLY, O_RDWR
    • 可选参数:
      • 创建文件:O_CREAT

        • 创建文件时检查文件是否存在:O_EXCL
        • 如果文件存在,返回-1
        • 必选与O_CREAT一起使用
      • 追加文件:O_APPEND
      • 文件截断:O_TRUNC
      • 设置非阻塞:O_NONBLOCK
    • mode: mode & ~umask(0777 & ~0002)
    > Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月04日 星期六 21时08分31秒
************************************************************************/#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>int main(int argc, const char* argv[]){// 打开一个文件helloint fd = open("hello", O_RDWR | O_CREAT, 0777);if(fd == -1){printf("打开失败\n");}close(fd);return 0;
}
  • read函数原型:

    • ssize_t read(int fd, void *buf, size_t count);
    • 参数:
      • fd:open函数的返回值
      • buf:缓冲区,存储要读取的数据
      • count:缓冲区能存储的最大字节数sizeof(buf)
    • 返回值:
      • -1:失败
      • 成功:
        • >0:读出的字节数
        • =0:文件读完了
  • write函数原型:

    • ssize_t write(int fd, const void *buf, size_t count);
    • 参数:
      • fd:open函数的返回值
      • buf:要写到文件中的数据
      • count:strlen(buf)
    • 返回值:
      • -1:失败
      • >0:写入到文件中的字节数
/************************************************************************> File Name: read_write.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月04日 星期六 21时34分47秒
************************************************************************/#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>int main(int argc,const char* argv[]){// 打开文件int fd = open("english.txt",O_RDWR);printf("fd = %d\n",fd);// 打开另一个文件,写操作int fd1 = open("temp", O_WRONLY | O_CREAT, 0664);printf("fd1 = %d\n", fd1);// readchar buf[4096]; int len = read(fd, buf, sizeof(buf));while(len > 0){// 数据写入文件中int ret = write(fd1, buf, len);printf("ret = %d\n", ret);// readlen = read(fd, buf, sizeof(buf));}close(fd);close(fd1);   return 0;
}
  • lseek函数原型:

    • off_t lseek(int fd, off_t offset, int whence);
    • whence参数:
      • SEEK_SET
      • SEEK_CUR
      • SEEK_END
    • 使用:
      • a.文件指针移动到头部;

        • lseek(fd, 0, SEEK_SET);
      • b.获取文件指针当前的位置;
        • int len = lseek(fd, 0, SEEK_CUR);
      • c.获取文件长度;
        • int len = lseek(fd, 0, SEEK_END);
    • 文件的拓展:
      • 文件原大小为100K,现在括扩展为1100K:lseek(fd, 1000, SEEK_END);
      • 最后,做一次写操作:write(fd, “a”, 1);
/************************************************************************> File Name: lessk.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月05日 星期日 10时40分22秒
************************************************************************/#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>int main(int argc, const char* argv[]){int fd = open("english.txt", O_RDWR);if(fd == -1){perror("open error");exit(1);}// 文件拓展int len = lseek(fd, 1000, SEEK_END);write(fd, "a", 1);printf("len=%d\n", len);close(fd);return 0;
}

6.perror和errno

  • 全局变量:errno,不同的值,对应不同的错误信息。
  • perror():打印错误的函数
/************************************************************************> File Name: read_write.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月04日 星期六 21时34分47秒
************************************************************************/#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>int main(int argc,const char* argv[]){// 打开文件int fd = open("english",O_RDWR);printf("fd = %d\n",fd);if(fd == -1){perror("open error");}// 打开另一个文件,写操作int fd1 = open("temp", O_WRONLY | O_CREAT, 0664);printf("fd1 = %d\n", fd1);// readchar buf[4096]; int len = read(fd, buf, sizeof(buf));while(len > 0){// 数据写入文件中int ret = write(fd1, buf, len);printf("ret = %d\n", ret);// readlen = read(fd, buf, sizeof(buf));}close(fd);close(fd1);return 0;
}

7.阻塞和非阻塞

  • 阻塞读终端程序分析:默认bash是前台程序,./a.out启动了一个程序,前台程序变成了./a.out,bash变成了后台程序。./a.out等待用户输入10个字符,实际输入的字符个数>10,剩下的字符还在缓冲区中。read函数解除阻塞,读缓冲区数据,执行write函数,./a.out程序结束执行。bash从后台程序变成了前台程序,然后检查到了缓冲区中剩余的字符,将字符作为shell命令去做解析。
/************************************************************************> File Name: block_read.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月05日 星期日 10时56分01秒
************************************************************************/#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>// 阻塞读终端
int main(void){char buf[10];int n;n = read(STDIN_FILENO, buf,10);if(n < 0){perror("read STDIN_FIFLENO");exit(1);}write(STDOUT_FILENO, buf, n);return 0;
}
  • 非阻塞读终端程序
/************************************************************************> File Name: unblock_read.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月05日 星期日 11时15分32秒
************************************************************************/#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#define MSG_TRY "try again\n"// 非阻塞读终端
int main(void){char buf[10];int fd, n;// /dev/tty---->当前打开的终端设备fd = open("/dev/tty", O_RDONLY | O_NONBLOCK);if(fd < 0){perror("open /dev/tty");exit(1);}tryagain:n = read(fd, buf,10);if(n < 0){// 如果write为非阻塞,但是没有数据可读,此时全局变量errno被设置为EAGAINif(errno == EAGAIN){sleep(3);write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));goto tryagain;}perror("read /dev/tty");exit(1);}write(STDOUT_FILENO, buf, n);close(fd);return 0;
}
  • 阻塞和非阻塞是文件的属性还是系统文件IO函数的属性?答案:文件的属性

    • 普通文件:例如:hello.c默认不阻塞
    • 终端设备:/dev/tty,默认阻塞
    • 管道/套接字:默认阻塞

8.stat/lstat函数

  • stat函数原型:

    • int stat(const char *pathname, struct stat *buf);
    • struct stat
struct stat {dev_t     st_dev;         // 文件的设备编号ino_t     st_ino;         // 节点mode_t    st_mode;        // 重点:文件的类型和存取的权限nlink_t   st_nlink;       // 连接到该文件的硬链接数目,刚建立的文件值为1uid_t     st_uid;         // 重点:用户IDgid_t     st_gid;         // 重点:用户组IDdev_t     st_rdev;        // 设备类型,若此文件为设备文件,则为其设备编号off_t     st_size;        // 重点:文件字节数(文件大小)blksize_t st_blksize;     // 块大小(文件系统的I/O缓冲区大小)blkcnt_t  st_blocks;      // 块数struct timespec st_atim;  // 最后一次访问时间struct timespec st_mtim;  // 重点:最后一次修改时间struct timespec st_ctim;  // 最后一次改变时间(指属性)};
  • 获取文件大小示例程序:
/************************************************************************> File Name: stat.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月05日 星期日 11时48分58秒
************************************************************************/#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>int main(int argc, const char* argv[]){struct stat st;int ret = stat("english.txt",&st);if(ret == -1){perror("stat error");exit(1);}printf("file size=%ld\n", st.st_size);return 0;
}
  • st_mode[16位整数]

    • 0-2bit–其他人权限

      • S_IROTH 00004(八进制表示) 读权限
      • S_IWOTH 00002 写权限
      • S_IXOTH 00001 执行权限
      • S_IRWXO 00007 掩码,过滤st_mode中除其他人权限以外的信息
    • 3-5bit–所属组权限
      • S_IRGRP 00040 读权限
      • S_IWGRP 00020 写权限
      • S_IXGRP 00010 执行权限
      • S_IRWXG 00070 掩码,过滤st_mode中除所属组权限以外的信息
    • 6-8bit–文件所有者权限
      • S_IRUSR 00400 读权限
      • S_IWUSR 00200 写权限
      • S_IXUSR 00100 执行权限
      • S_IRWXU 00700 掩码,过滤st_mode中除文件所有者权限以外的信息
    • 12-15bit–文件类型
      • S_IFSOCK 0140000 套接字
      • S_IFLNK 0120000 符号链接(软链接)
      • S_IFREG 0100000 普通文件
      • S_IFBLK 0060000 块设备
      • S_IFDIR 0040000 目录
      • S_IFCHR 0020000 字符设备
      • S_IFIFO 0010000 管道
      • S_IFMT 0170000 掩码,过滤st_mode中除文件类型以外的信息
/************************************************************************> File Name: stat.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月05日 星期日 11时48分58秒
************************************************************************/#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>int main(int argc, const char* argv[]){struct stat st;int ret = stat("english.txt",&st);if(ret == -1){perror("stat error");exit(1);}printf("file size=%ld\n", st.st_size);// 文件类型--判断是否为普通文件if((st.st_mode & S_IFMT) == S_IFREG){printf("这个文件是一个普通文件\n");}// 文件所有者操作权限if(st.st_mode & S_IRUSR){printf("    r\n");}if(st.st_mode & S_IWUSR){printf("    w\n");}if(st.st_mode & S_IXUSR){printf("    x\n");}return 0;
}

  • lstat函数原型:

    • int lstat(const char *pathname, struct stat *buf);
    • struct stat
struct stat {dev_t     st_dev;         // 文件的设备编号ino_t     st_ino;         // 节点mode_t    st_mode;        // 重点:文件的类型和存取的权限nlink_t   st_nlink;       // 连接到该文件的硬链接数目,刚建立的文件值为1uid_t     st_uid;         // 重点:用户IDgid_t     st_gid;         // 重点:用户组IDdev_t     st_rdev;        // 设备类型,若此文件为设备文件,则为其设备编号off_t     st_size;        // 重点:文件字节数(文件大小)blksize_t st_blksize;     // 块大小(文件系统的I/O缓冲区大小)blkcnt_t  st_blocks;      // 块数struct timespec st_atim;  // 最后一次访问时间struct timespec st_mtim;  // 重点:最后一次修改时间struct timespec st_ctim;  // 最后一次改变时间(指属性)};
  • stat函数与lstat函数的区别:在于读取软链接文件时不同。

    • lstat读取的是链接文件本身的属性
    • stat读取的是链接文件指向的文件的属性(追踪、穿透)
/************************************************************************> File Name: stat.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月05日 星期日 11时48分58秒
************************************************************************/#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>int main(int argc, const char* argv[]){struct stat st;int ret = lstat("s.s",&st);if(ret == -1){perror("stat error");exit(1);}printf("file size=%ld\n", st.st_size);// 文件类型--判断是否为普通文件if((st.st_mode & S_IFMT) == S_IFREG){printf("这个文件是一个普通文件\n");}// 文件所有者操作权限if(st.st_mode & S_IRUSR){printf("    r");}if(st.st_mode & S_IWUSR){printf("    w");}if(st.st_mode & S_IXUSR){printf("    x");}printf("\n");return 0;
}

9.文件属性相关的函数

  • access()试当前用户指定文件是否具有某种属性

    • 当前用户:使用哪个用户调用这个函数,这个用户就是当前用户。
    • int access(const char *pathname, int mode);
      • 参数:

        • pathname:文件名
        • mode:4种权限
          • R_OK 读
          • W_OK 写
          • X_OK 执行
          • F_OK 文件是否存在
        • 返回值:
          • 0:有某种权限或文件存在
          • -1":没有或文件不存在
/************************************************************************> File Name: access.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月05日 星期日 15时40分48秒
************************************************************************/#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, const char* argv[]){if(argc < 2){printf("a.out filename\n");exit(1);}int ret = access(argv[1],W_OK );if(ret == -1){perror("access");exit(1);}printf("you can write this file.\n");return 0;
}
  • chmod()修改文件权限

    • int chmod(const char *pathname, mode_t mode);
    • 参数:
      • pathname:文件名
      • mode:文件权限,八进制数
  • chown()修改文件所有者和所属组

    • int chown(const char *pathname, uid_t owner, gid_t group);
    • 参数:
      • pathname:文件名
      • owner:整型值,用户ID
        • 用户ID的查看:/etc/passwd
      • group:整型值,用户组ID
        • 用户组ID的查看:/etc/group
/************************************************************************> File Name: chmod.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月05日 星期日 15时50分54秒
************************************************************************/#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>int main(int argc, const char* argv[]){if(argc < 3){printf("a.out filename mode\n");exit(1);}int mode = strtol(argv[2], NULL, 8);int ret = chmod(argv[1], mode);if(ret == -1){perror("chmod");exit(1);}ret = chown(argv[1], 1001, 1002);if(ret == -1){perror("chown");exit(1);}return 0;
}
  • truncate()修改文件大小

    • int truncate(const char *path, off_t length);
    • 参数:
      • path:文件名
      • length:文件的最终大小
        • 比原来小,删除后面的部分
        • 比原来大,向后扩展

10.目录属性相关的函数

  • rename()文件重命名

    • int rename(const char *oldpath, const char *newpath);
  • 修改当前进程(应用程序)的路径,相当于cd命令
    • int chdir(const char *path);
    • 参数:切换的路径
  • 获取当前进程的工作目录,相当于pwd命令
    • char *getcwd(char *buf, size_t size);
    • 返回值:
      • 成功:当前的工作目录
      • 失败:NULL
    • 参数:
      • buf:缓冲区,存储当前的工作目录
      • size:缓冲区大小
  • 创建目录,相当于mkdir命令
    • int mkdir(const char *pathname, mode_t mode);
    • 参数:
      • pathname:创建的目录名
      • mode:目录权限,八进制的数,实际权限:mode & ~umask
  • 删除一个空目录
    • int rmdir(const char *pathname);
    • 参数:空目录的名字
/************************************************************************> File Name: chdir.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月05日 星期日 16时07分20秒
************************************************************************/#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, const char* argv[]){if(argc < 2){printf("a.out dir\n");exit(1);}int ret = chdir(argv[1]);if(ret == -1){perror("chdir");exit(1);}int fd = open("chdir.txt", O_CREAT | O_RDWR, 0777);if(fd == -1){perror("open");exit(1);}close(fd);char buf[128];getcwd(buf, sizeof(buf));printf("current dir: %s\n", buf);return 0;
}

11.目录遍历相关的函数

  • (1).打开一个目录opendir()

    • DIR *opendir(const char *name);

      • 参数:目录名
      • 返回值:指向目录的指针
  • (2).读目录

    struct dirent {ino_t d_ino;  // 此目录进入点的inodeff_t d_off;  // 目录文件开头至此目录进入点的位移signed short ind d_reclen;  // d_name的长度,不包含NULL字符unsigned char d_type;  // 重点:d_name所指的文件类型har d_name[256];  // 重点:文件名
    };
    
  • d_type:

    • DT_BLK:块设备
    • DT_CHR:字符设备
    • DT_DIR:目录
    • DT_LNK:软链接
    • DT_FIFO:管道
    • DT_REG:普通文件
    • DT_SOCK:套接字
    • DT_UNKNOWN:未知
  • struct dirent* readdir(DIR* dirp);

    • 参数:opendir的返回值
    • 返回值:目录项结构体
  • (3).关闭目录

    • int closedir(DIR *dirp);
/************************************************************************> File Name: getfilenumber.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月05日 星期日 21时24分32秒
************************************************************************/#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>// 读指定目录中的文件个数
int get_file_num(const char* root){int total = 0;// 读目录DIR* dir = NULL;dir = opendir(root);if(dir == NULL){perror("opendir error");exit(1);}// 循环读目录中的文件struct dirent* ptr = NULL;while((ptr = readdir(dir)) != NULL){// 不处理.和..目录if(strcmp(".", ptr->d_name) == 0 || strcmp("..", ptr->d_name) == 0){continue;}// 判断是否是普通文件if(ptr->d_type == DT_REG){total++;}// 如果是目录,则需要递归if(ptr->d_type == DT_DIR){// 求出子目录char path[1024] = {0};sprintf(path, "%s/%s", root, ptr->d_name);total += get_file_num(path);}}// 关闭目录closedir(dir);return total;
}int main(int argc, const char* argv[]){if(argc < 2){printf("./a.out path\n");exit(1);}int total = get_file_num(argv[1]);printf("%s目录下的普通文件共有:%d个\n", argv[1],total);return 0;
}

12.dup、dup2和fcntl函数

  • 复制文件描述符

    • int dup(int oldfd);
    • 参数:oldfd要复制的文件描述符
    • 返回值:取最小的且没被占用的文件描述符
    • dup调用成功:有两个文件描述符指向同一个文件
    • int dup2(int oldfd, int newfd);
      • 假设:oldfd指向hello文件,newfd指向world文件

        • a.假设newfd已经指向了一个文件,首先断开close与那个文件的链接,newfd指向oldfd指向的文件(文件描述符的重定向)
        • b.newfd没有被占用,newfd指向oldfd指向的文件
        • c.oldfd和newfd指向同一个文件,不做任何处理
  • 改变已经打开的文件的属性:fcntl

    • 变参函数
    • 复制一个已有的文件描述符:int ret = fcntl(fd, F_DUPFD)
    • 获取/设置文件状态标志
      • open的flags参数
      • 获取文件状态标识:int flag = fcntl(fd, F_GETFL)
      • 设置文件状态标识:
        • flag = flag | O_APPEND;
        • fcntl(fd, F_SETFL, flag)
      • 可更改的几个标识:O_APPEND、O_NONBLOCK(常用)
        int dup2(int oldfd, int newfd);
/************************************************************************> File Name: dup.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月05日 星期日 22时07分30秒
************************************************************************/#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>int main(void){int fd = open("tmp", O_RDWR | O_CREAT, 0664);if(fd == -1){perror("open");exit(1);}// 复制文件描述符int fd2 = dup(fd);
//  int fd2 = fcntl(fd, F_DUPFD);// 写文件char* p = "代码改变世界...";write(fd2, p, strlen(p));close(fd2);char buf[1024];lseek(fd, 0, SEEK_SET);read(fd, buf, sizeof(buf));printf("buf = %s\n", buf);close(fd);return 0;
}/************************************************************************> File Name: dup2.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月05日 星期日 22时07分30秒
************************************************************************/#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>int main(void){int fd = open("tmp", O_RDWR | O_CREAT | O_APPEND, 0664);if(fd == -1){perror("open");exit(1);}int fd2 = open("tmp1", O_RDWR | O_CREAT | O_APPEND, 0664);if(fd2 == -1){perror("open open");exit(1);}// 复制文件描述符dup2(fd, fd2);// 写文件char* p = "code change the world...";write(fd2, p, strlen(p));close(fd2);char buf[1024];lseek(fd, 0, SEEK_SET);read(fd, buf, sizeof(buf));printf("buf = %s\n", buf);close(fd);return 0;
}/************************************************************************> File Name: fcntl.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月05日 星期日 22时28分26秒
************************************************************************/#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main(void)
{int fd;int flag;// 测试字符串char *p = "我们是一个有中国特色的社会主义国家!!!!!!";char *q = "呵呵, 社会主义好哇。。。。。。";// 只写的方式打开文件fd = open("test.txt", O_WRONLY);if(fd == -1){perror("open");exit(1);}// 输入新的内容,该部分会覆盖原来旧的内容if(write(fd, p, strlen(p)) == -1){perror("write");exit(1);}// 使用 F_GETFL 命令得到文件状态标志flag = fcntl(fd, F_GETFL, 0);if(flag == -1){perror("fcntl");exit(1);}// 将文件状态标志添加 ”追加写“ 选项flag |= O_APPEND;// 将文件状态修改为追加写if(fcntl(fd, F_SETFL, flag) == -1){perror("fcntl -- append write");exit(1);}// 再次输入新内容,该内容会追加到旧内容的后面if(write(fd, q, strlen(q)) == -1){perror("write again");exit(1);}// 关闭文件close(fd);return 0;
}/************************************************************************> File Name: fc.c> Author: CurryCoder> Mail: 1217096231@qq.com > Created Time: 2020年07月05日 星期日 22时30分16秒
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main(void)
{int fd;int flag;// 测试字符串char *p = "我们是一个有中国特色的社会主义国家!!!!!!";char *q = "我无言以对,只能呵呵。。。。。。";// 只写的方式打开文件fd = open("test.txt", O_RDONLY);if(fd == -1){perror("open");exit(1);}// 使用 F_GETFL 命令得到文件状态标志flag = fcntl(fd, F_GETFL, 0);if(flag == -1){perror("fcntl");exit(1);}flag = O_RDWR;if(fcntl(fd, F_SETFL, flag) == -1){perror("fcntl -- append write");exit(1);}// 再次输入新内容,该内容会追加到旧内容的后面if(write(fd, q, strlen(q)) == -1){perror("write again");exit(1);}// 关闭文件close(fd);return 0;
}

Linux系统函数之IO函数相关推荐

  1. 【Linux系统编程】vfork() 函数详解

    00. 目录 文章目录 00. 目录 01. vfork函数 02. fork和vfork区别 03. 父子进程地址空间 04. 附录 01. vfork函数 函数分析 #include <sy ...

  2. 【Linux系统编程】fork()函数详解

    00. 目录 文章目录 00. 目录 01. 进程创建函数 02. 父子进程结构 03. 父子进程地址空间 04. 附录 01. 进程创建函数 #include <sys/types.h> ...

  3. Linux系统shell脚本之函数的使用

    Linux系统shell脚本之函数的使用 一.函数解释 二.函数参数 1.参数注意事项 2.特殊参数说明 三.函数实例1 四.函数实例2 一.函数解释 1.函数(function)作用:函数可以在sh ...

  4. Linux系统进阶-基础IO

    Linux系统进阶-基础IO 文章目录 Linux系统进阶-基础IO C语言中的文件接口 对文件进行写入 对文件进行读取 什么是当前路径 默认打开的三个流 stdout & stderr 系统 ...

  5. Linux系统下基于IO多路复用的大规模可靠UDP服务器的实现(三)

    七.可靠性UDP的优化细节 4.5章节中,我们提到了KCP本身的优化提高,由于可靠性UDP是这个方案是否优秀的关键,而各种可靠UDP协议中都有TCP算法的影子,所以下面我们再仔细的谈一下这个部分.按照 ...

  6. 【Linux系统编程】IO标准缓冲区

    00. 目录 文章目录 00. 目录 01. 缓冲区概述 02. 全缓冲 03. 行缓冲 04. 不带缓冲区 05. 附录 01. 缓冲区概述 标准I/O提供了三种类型的缓冲: 1.全缓冲: 在填满标 ...

  7. linux系统如何使用fork函数创建子进程

    大家都知道linux是多进程的系统.可是,在linux中,进程是如何创建并运行的呢? 在linux系统中创建进程有两种方式:一是由操作系统创建,二是由父进程创建进程(通常为子进程).系统调用函数for ...

  8. linux系统编程:暂停函数pause

    pause函数 该函数功能主要是暂停进程,它的返回值总是-1. 使用方式: (1)首先使用signal函数提前注册一个中断函数,该函数用于将函数指针和信号做一个绑定; (2)当程序进行执行pause, ...

  9. linux原子过程,linux系统编程:IO读写过程的原子性操作实验

    所谓原子性操作指的是:内核保证某系统调用中的所有步骤(操作)作为独立操作而一次性加以执行,其间不会被其他进程或线程所中断. 举个通俗点的例子:你和女朋友OOXX的时候,突然来了个电话,势必会打断你们高 ...

最新文章

  1. oracle数据库连接设置配置文件
  2. Go语言Flag的简单示例
  3. STM32 基础系列教程 44 - FSMC_LCD
  4. ibatis中多表联接查询
  5. dataframe保存为txt_如何批量查找并修改替换 Word、PPT、Excel、PDF、TXT等文件的内容...
  6. faster rcnn学习之rpn、fast rcnn数据准备说明
  7. JSP 登录案例实现
  8. Java例外:java lang NoSuchMethodError
  9. 《并行计算的编程模型》一3.8.3 原子交换和条件交换
  10. web监听器监听mysql_JavaWEB开发15——ListenerListener
  11. 湖南计算机保密防范系统,保密技术防护专用系统
  12. Qy词典-免费离线的中英词典
  13. Oracle SQL计算周
  14. jq css3实现跑马灯+大转盘
  15. 【绿色版软件】出现应用程序无法启动,并行配置不正确
  16. vue 获取动态域名_vue项目接口域名动态获取操作
  17. 大学计算机编程考试用什么软件?
  18. 深入浅出推荐系统(二):召回:内容为王
  19. 室内设计软件:3D Interior Design 2022
  20. 四路抢答器的控制程序设计

热门文章

  1. NOIP2018 集训(一)
  2. 个人信息泄露致电信诈骗猖獗 专家:治理亟须完善立法
  3. 转 PHP编程过程中需要了解的this,self,parent的区别
  4. hibernate多个主键
  5. SQL SERVER错误:已超过了锁请求超时时段。 (Microsoft SQL Server,错误: 1222)
  6. linux高级数据存储
  7. GIT之git常用配置和操作
  8. Serverless 时代下大规模微服务应用运维的最佳实践
  9. Spring Security 中最流行的权限管理模型!
  10. 3种 Springboot 全局时间格式化方式,别再写重复代码了