Linux中,一切皆文件!
=============== 1.文件IO ====================
浏览书本:《4.2.1系统IO》和《4.2.2标准IO》
问题:
相同点:两种方式都是用于操作文件。
不同点:
系统IO:在操作系统层面,由系统提供。
标准IO:在库函数层面,由标准C库提供。
(关系:标准IO函数,其本质也是调用系统IO)
系统IO:由系统提供,有最基本的操作函数。(简洁、精炼)(类似于菜市场)
好处:简洁单一,稳定,不需要消耗过多系统资源。
缺点:对于功能性要求较高的程序,更加繁琐。
标准IO:由标准C库提供,拥有多样化的操作函数。(功能多样)(类似于饭馆)
好处:复杂操作更为方便,函数接口更加多样化。
缺点:消耗系统资源更多,不适用于简单功能。
=============== 2.系统IO ====================
——》在操作系统层面,由系统提供。
常用的接口函数:
备注:
=============== 3.主函数传参功能 ====================
主函数形式:
int main()
int main(void) //等同于上一个
int main(int argc, const char *argv[])
int main(int argc, const char **argv)
=============== 4.系统IO常用函数 ====================
#include <sys/ioctl.h>
int ioctl(int fd, unsigned long request, ...);
备注:
比如6818开发板的蜂鸣器驱动有3个参数:
int ioctl(蜂鸣器硬件文件描述符, 电平状态, 引脚号);
蜂鸣器设备:”/dev/beep”
电平状态: 低电平0,高电平1(分别控制蜂鸣器响/不响)
引脚号: 固定为1号引脚
2. 复制文件描述符:
dup和dup2
备注:
3. 文件控制:(软件、硬件。。)
fcntl()
备注:
4. 内存映射 (作用:将文件与内存进行关联,提高操作效率!)
mmap()
空洞文件有什么用呢?空洞文件对多线程共同操作文件是及其有用的,有时候我们创建一个很大的文件,如果单个线程从头开始依次构建该文件需要很长的时间,有一种思路就是将文件分为多段,然后使用多线程来操作,每个线程负责其中一段数据的写入;这个有点像我们现实生活当中施工队修路的感觉,比如说修建一条高速公路,单个施工队修筑会很慢,这个时候可以安排多个施工队,每一个施工队负责修建其中一段,最后将他们连接起来。
来看一下实际中空洞文件的两个应用场景:
在使用迅雷下载文件时,还未下载完成,就发现该文件已经占据了全部文件大小的空间,这也是空洞文件;下载时如果没有空洞文件,多线程下载时文件就只能从一个地方写入,这就不能发挥多线程的作用了;如果有了空洞文件,可以从不同的地址同时写入,就达到了多线程的优势;
在创建虚拟机时,你给虚拟机分配了 100G 的磁盘空间,但其实系统安装完成之后,开始也不过只用了 3、4G 的磁盘空间,如果一开始就把 100G 分配出去,资源是很大的浪费。
1.open.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
// 文件路径:
//相对路径:1.txt
//绝对路径:/mnt/hgfs/GZ2203/04 文件IO/01 系统IO/code/1.txt
int fd; // 文件描述符(操作句柄,文件编号)
fd = open("1.txt", O_RDWR);
if(fd == -1)
{
perror("open failed"); // 打印错误信息
return -1;
}
printf("open success![%d]\n", fd);
return 0;
}
2.open_close.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
// 文件路径:
//相对路径:1.txt
//绝对路径:/mnt/hgfs/GZ2203/04 文件IO/01 系统IO/code/1.txt
int fd; // 文件描述符(操作句柄,文件编号)
int cnt=1;
while(1)
{
// 打开
fd = open("1.txt", O_RDWR);
if(fd == -1)
{
perror("open failed"); // 打印错误信息
return -1;
}
printf("open success![%d][%d]\n", fd, cnt++);
// 关闭
// close(fd);
}
return 0;
}
3.creat.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
// 文件路径:
//相对路径:1.txt
//绝对路径:/mnt/hgfs/GZ2203/04 文件IO/01 系统IO/code/1.txt
int fd; // 文件描述符(操作句柄,文件编号)
// 打开
fd = open("a.txt", O_RDWR|O_CREAT|O_EXCL, 0644);
if(fd == -1)
{
perror("open failed"); // 打印错误信息
return -1;
}
printf("open success![%d]\n", fd);
// 关闭
close(fd);
return 0;
}
4.write.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
// 文件路径:
//相对路径:1.txt
//绝对路径:/mnt/hgfs/GZ2203/04 文件IO/01 系统IO/code/1.txt
int fd; // 文件描述符(操作句柄,文件编号)
// 1.打开(不存在则创建,存在则直接打开)
fd = open("1.txt", O_RDWR|O_CREAT, 0644);
if(fd == -1)
{
perror("open failed"); // 打印错误信息
return -1;
}
printf("open success![%d]\n", fd);
// 2.写入
// sizeof(str1) :计算的是指针的大小(64位都是8字节)
char *str1 = "a";
int n_write = write(fd, str1, strlen(str1));
printf("%d write\n", n_write);
// 关闭
close(fd);
return 0;
}
5.read.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
// 文件路径:
//相对路径:1.txt
//绝对路径:/mnt/hgfs/GZ2203/04 文件IO/01 系统IO/code/1.txt
int fd; // 文件描述符(操作句柄,文件编号)
// 1.打开
fd = open("1.txt", O_RDONLY, 0644);
if(fd == -1)
{
perror("open failed"); // 打印错误信息
return -1;
}
printf("open success![%d]\n", fd);
// 2.读取
char r_buf[10];
bzero(r_buf, sizeof(r_buf));
int n_read = read(fd, r_buf, sizeof(r_buf));
printf("[%d]: %s\n", n_read, r_buf);
// 3.关闭
close(fd);
return 0;
}
6.lseek偏移
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
// 文件路径:
//相对路径:1.txt
//绝对路径:/mnt/hgfs/GZ2203/04 文件IO/01 系统IO/code/1.txt
int fd; // 文件描述符(操作句柄,文件编号)
// 1.打开
fd = open("1.txt", O_RDWR);
if(fd == -1)
{
perror("open failed"); // 打印错误信息
return -1;
}
printf("open success![%d]\n", fd);
// 2.写入
char w_buf[100] = "Lisi";
int n_write = write(fd, w_buf, strlen(w_buf));
printf("%d write\n", n_write);
// 3.文件偏移量修改
// lseek(fd, -4, SEEK_CUR); // 从当前位置向前偏移4个字节
lseek(fd, 0, SEEK_SET); // 从文件开头,不偏移
// 4.读取
char r_buf[10];
bzero(r_buf, sizeof(r_buf));
int n_read = read(fd, r_buf, sizeof(r_buf));
printf("read[%d]: %s\n", n_read, r_buf);
// 5.关闭
close(fd);
return 0;
}
7.读写偏移.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
// 1.打开文件
int fd;
fd = open("1.txt", O_RDWR);
if(fd == -1)
{
perror("open failed");
return -1;
}
// 2.输入名字并写入指定位置
char name[10] = {0};
printf("Pls Input: ");
scanf("%s", name); while(getchar()!='\n');
// 偏移到指定位置并写入
lseek(fd, 6, SEEK_SET);
write(fd, name, strlen(name));
// 3.读取文件内容
// 偏移到开头并读取
lseek(fd, 0, SEEK_SET);
char r_buf[100];
bzero(r_buf, sizeof(r_buf));
int n_read = read(fd, r_buf, sizeof(r_buf));
printf("read(%d): %s\n", n_read, r_buf);
// 4.关闭文件
close(fd);
return 0;
}
8.主函数传参.c
#include <stdio.h>
// 主函数
// arg:argument形参简称
// c:count计数
// v:varible变量
// int main(int argc, const char *argv[])
int main(int argc, const char **argv)
{
int i;
for(i=0; i<argc; i++)
printf("argv[%d]: %s\n", i, argv[i]);
return 0;
}
9.ioctl控制蜂鸣器.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
int main()
{
// 1.打开蜂鸣器
int beep_fd = open("/dev/beep", O_RDWR);
if(beep_fd == -1)
{
perror("open beep failed");
return -1;
}
// 2.控制蜂鸣器
int i;
for(i=0; i<3; i++)
{
ioctl(beep_fd, 0, 1); //响
sleep(1);
ioctl(beep_fd, 1, 1); //不响
sleep(1);
}
// 3.关闭蜂鸣器
close(beep_fd);
return 0;
}
10.dip和dup2复制文件描述符.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
int main()
{
int fd = open("1.txt", O_RDWR);
if(fd == -1)
{
perror("open failed");
return -1;
}
// 复制文件描述符,由系统分配新的文件描述符(最小、未用)
int new_fd1 = dup(fd);
char ch;
lseek(fd, 0, SEEK_SET);
read(fd, &ch, 1);
printf("fd(%d): %c\n", fd, ch);
lseek(new_fd1, 0, SEEK_SET);
read(new_fd1, &ch, 1);
printf("new_fd1(%d): %c\n", new_fd1, ch);
// 复制文件描述符,自行指定新的文件描述符
int new_fd2 = dup2(fd, 100);
lseek(new_fd2, 0, SEEK_SET);
read(new_fd2, &ch, 1);
printf("new_fd2(%d): %c\n", new_fd2, ch);
return 0;
}