目录
一:Linux内核函数
Linux内核函数【文件系统调用】
open系统调用
read系统调用
write系统调用
create系统调用
close系统调用
mkdir系统调用
…
需要学会在ubuntu中自己查看函数,并且学会使用函数
命令示例 man 2 open 查看open函数的使用说明
man open
man 2 open
查看完使用手册之后,按下q退出手册
二:ubuntu环境下的文件掩码
umask 文件掩码 umask查看 默认文件掩码是 0022 如下图所示
umask
默认的文件掩码是0022
对于0022,首先需要先了解一下 9个权限位
目录第一位是 d
文件第一位是 -
9个权限位 3个为一组 分为:
文件拥有者 、同组 、其他用户
rwx rwx rwx
[3个为一组,第一组文件拥有者、第二组为同组、第三组为其他用户]
r: 可读 4
w: 可写 2
x: 可执行 1
都可以则4+2+1=7
可读可写可执行 : 0777
三:VS2019 Linux跨平台开发
对初次使用VS2019,在Linux控制台编译运行 这个使用过程不大了解的朋友们
可以阅读下这个小节
【window下创建工程编写代码 Linux环境下编译运行程序】
首先 右键新建项目
选择空项目
选择C++
选择Linux
工程名称命令 存储位置设置
右键项目、添加、新建项
可以规范命名为:main.cpp
运行测试中必须要设置断点 (window下编程,Linux下运行,跨平台开发)
对于跨平台编程要求:严格编写代码、换行必不可少
因为 Linux控制台输出,需要换行标识、断点,来确定结束位
点击全部保存
点击运行
在运行结束后可以点击上方小红框结束运行
以上即为VS2019跨平台编程的基础使用
四:Linux控制台输出
window环境下 VS2019编写的代码工程
保存在
Linux环境下 home目录下 project中
open函数 使用示例
#include<iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
using namespace std;
int main()
{
open("/root/123.txt", O_CREAT | O_WRONLY, 0777);
return 0;
}
在Linux环境下,看出 123.txt创建成功
可视化操作查看一下新创建的123.txt的文件权限
也可以使用 命令的方式 来查看一下新创建的123.txt的文件权限
在这个查看过程中可以发现
无论可视化还是命令行查看文件权限
均不符合自己代码所设置的文件权限 [0777 可读可写可执行]
现在查看到的权限位是
-rwxr-xr-x也就是0755
为什么编程中设置文件权限为0777,最后创建的文件权限却是0755呢???
因为权限掩码umask 0022的存在:0777-0022即是0755
清除命令 clear
clear
umask 查看一下文件掩码 0022
umask
权限掩码也就是做一个权限保护
不过可以在编程中也是可以修正的:umask(0);【文件权限设置为所写即所得】
#include<iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include <unistd.h>
#include <string.h>
using namespace std;
int main()
{
umask(0);
open("/root/123.txt", O_CREAT | O_WRONLY, 0777);
return 0;
}
在使用了umask(0);后,再可视化查看一下123.txt的文件权限
也可以使用 命令的方式 查看一下123.txt的文件权限
可以看到123.txt权限为可读可写可执行,因此umask(0);需要记得在设置权限时补充
五:open函数
在Linux环境下
可以使用命令查看手册进行学习open函数 man 2 open
man 2 open
如上图,可以看出两种写法的返回都是int类型
往下 可以查看 参数说明
再往下可以看到return value返回值说明
都会返回一个新的[文件描述符 (fd)]
file descriptor文件描述符,可简写为fd
或者会返回-1(代表错误)
对于文件描述符的值也是可以打印查看的
可以先把linux环境下的123.txt文件删掉
再次运行代码
#include<iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
using namespace std;
int main()
{
umask(0);
int fd = open("/root/123.txt", O_CREAT | O_WRONLY, 0777);
cout << "fd = " << fd << endl;
return 0;
}
可以看到:fd文件描述符值为3 ,为什么呢?
特殊文件描述符号
标准输入STDIN_FILENO
标准输出STDOUT_FILENO
标准错误STDERR_FILENO
每个进程被加载后,默认打开0,1,2这三个文件描述符
操作系统本身有的0 1 2已经占用,所以自己创建的文件描述符fd=3
int fd = open("/root/123.txt", O_CREAT | O_WRONLY, 0777);
再次执行如上代码:文件不存在会创建文件,文件存在则是打开而不是再创建
perror 来自库函数 stdio.h
六:write函数
可以打开手册学习函数使用
man write
这个BSD不是自己想查看的
在ubuntu中查看内核函数使用手册
man xxx 若是不可以查看到,就 man 2 xxx
man 2 write
如上图才是write函数的使用手册
在编程时候,可复制头文件,使用write函数
文件分为两种:
一种是纯字符文件(文件中只有字符,没有其他,如txt,cpp,.h文件)
还有一个叫二进制文件(音频视频压缩包图片)
以ppt为例,ppt是二进制文件(因为可以放视频图片)
word文档是二进制文件(可以放图片)
如果成功,已经写入的字节会被返回(写入多少字节),返回写入的字节数,写成功返回大于0的数字
七:read函数
查看函数说明手册
man read
如上图,由void *buf 知道 write和read函数是可以操作任意数据的
#include<iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include <unistd.h>
#include <string.h>
using namespace std;
int main()
{
char buf[50] = {"hello linux"};
umask(0);
int fd = open("/root/123.txt", O_CREAT | O_WRONLY, 0777);
if (fd == -1)
{
perror("open error");
}
else
{
cout << "fd = " << fd << endl;
int res = write(fd, buf, sizeof(buf));
cout << "res = " << res << endl;
}
return 0;
}
int res = write(fd, buf, sizeof(buf));
write函数返回
sizeof是要写入的长度,在代码中开空间是50
最后写入的字节数也是50
但是\00是属于没用的字符
可以先删除123.txt文件,再重新休整
因此需要将sizeof修改为strlen
忘记strlen头文件可以man查看一下
#include<iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include <unistd.h>
#include <string.h>
using namespace std;
int main()
{
char buf[50] = {"hello linux"};
umask(0);
int fd = open("/root/123.txt", O_CREAT | O_WRONLY, 0777);
if (fd == -1)
{
perror("open error");
}
else
{
cout << "fd = " << fd << endl;
int res = write(fd, buf, strlen(buf));
cout << "res = " << res << endl;
}
return 0;
}
若Linux中没有删除123.txt文件
将char buf[50] = {"hello linux"};修改为char buf[50] = {"xxx"};
看下文件内容是否会被覆盖
这里的res是3字节(xxx)
但查看到的是11字节
因此说明是 从头覆盖了文件内容
由上述可知 若要追加内容,就直接使用追加(如下)
八:文件的拷贝操作
read函数
头文件、函数原型、函数返回
返回值是0就是文件末尾
错误是返回-1或者返回错误码
#include<iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include <unistd.h>
#include <string.h>
using namespace std;
int main()
{
char buf[50] = { 0 };
umask(0);
int wfd = open("/root/copy1.txt", O_CREAT | O_WRONLY, 0777);
int rfd = open("/root/123.txt", O_RDONLY, 0777);
if (wfd == -1 || rfd == -1)
{
perror("open error");
}
else
{
int res = 0;
while ((res = read(rfd, buf, sizeof(buf))) > 0)
{
int ws = write(wfd, buf, res);
cout << "ws = " << ws << endl;
}
close(rfd);
close(wfd);
cout << "success" << endl;
}
return 0;
}
Linux控制台窗口中显示:6X50+30=330
成功拷贝 123.txt文件
拷贝生成有 copy1.txt
若是将res修改sizeof,如下修改,再测试
int ws = write(wfd, buf, res);
int ws = write(wfd, buf, sizeof(buf));
Linux控制台显示:都是50
Linux环境下,查看copy1.txt是350字节[出错]
对比上下图,不难看出拷贝出来的内容是错误的
若是res修改为strlen,如下修改,再测试
int ws = write(wfd, buf, strlen(buf));
Linux控制台显示:都是54明显出错
原先330字节后面拷贝出378字节[明显出错]
对比查看,可以明显看出拷贝出的是错误的信息
综上测试
只能 res 读多少写多少 符合标准
int ws = write(wfd, buf, res);
当然,也可以拷贝图片
如下图所示,将3.jpg图片拷贝一份
拷贝图片
#include<iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include <unistd.h>
#include <string.h>
using namespace std;
int main()
{
char buf[50] = { 0 };
umask(0);
int wfd = open("/root/copy3.jpg", O_CREAT | O_WRONLY, 0777);
int rfd = open("/root/3.jpg", O_RDONLY, 0777);
if (wfd == -1 || rfd == -1)
{
perror("open error");
}
else
{
int res = 0;
while ((res = read(rfd, buf, sizeof(buf))) > 0)
{
int ws = write(wfd, buf, res);
cout << "ws = " << ws << endl;
}
close(rfd);
close(wfd);
cout << "success" << endl;
}
return 0;
}
图片成功拷贝