Linux学习之系统编程1(关于读写系统函数)

写在前面:

我的Linux的学习之路非常坎坷。第一次学习Linux是在大一下的开学没多久,结果因为不会安装VMware就无疾而终了,可以说是没开始就失败了。第二次学习Linux是在大一下快放暑假(那个时候刚刚过完考试周),我没什么事做就又重拾Linux,不服输的我选择再战Linux,这一次学习还算顺利,虽然中间有些小插曲但是不影响整体学习进度, 我看着B站上的视频一点点学习Linux,基本上把Linux的基础指令学完了。学完之后我又遇到问题了,视频基本上到这就结束了,而我却不知道下一步该学什么,于是就没怎么碰Linux,结果没过多长时间我就把学的Linux指令忘的一干二净。现在是我第三次学习Linux,我决定重新开始学Linux,同时为了让自己学习的效果更好,我选择以写blog的形式逼迫自己每天把学习到的Linux知识整理下来。这也就是我写这个系列blog的原因。


好久没更新了,虽然这几天我并没有停止学习Linux,但是时间确实有点不够,写一篇blog还是比较耗时间的。(好吧,其实就是我有点懒,明明可以挤出时间,但是还是去划水了)


open函数

当遇到我们不熟悉的函数,我们可以去manpage查看,这也是一个非常重要的自主学习手段和方法

manpage 第二卷,直接man 2 open就可以查看open函数的的详细信息。
open1

根据上面的描述,我们可以得知open的基本信息

  • 要使用open需要引头文件sys/types.hsys/stat.h>fcntl.h(其中sys/types.hsys/stat.h>这两个头文件可以用unistd.h来替代。
  • 传入的第一个参数类型是const char*,看名称就可以猜到是要打开文件的路径,这里用绝对路径和相对路径都可以。
  • 传入的第二个参数类型是int,这里没有详细写,我就简单介绍,这个flag是权限控制,有O_RDONLY O_WRONLY O_RDWR,分别表示只读,只写,读写。(其实和C语言里的库函数fopen差不多)
  • 对于第二个open就是多了个参数mode_t mode,就是当文件不存在时,我们创建文件(前面那个flag参数还要指定O_CREAT才可以创建文件),指定文件的权限。(文件权限=mode&~umask)

关于返回值

open2
简单来说就是一个文件描述符,用它可以读写文件。这里实在理解不了的,可以把它理解成一个非负整数,用它来操作文件,后面我会详细讲解这个文件描述符。

使用open常见的错误

  • 打开文件不存在
  • 以写方式打开只读文件(权限问题)
  • 以只写方式打开目录

下面我举例演示

源代码:

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>int main()
{int fd;fd=open("./test.c",O_RDONLY);if(fd<0){printf("fd=%d,errno=%d:%s",fd,errno,strerror(errno));exit(0);}printf("fd=%d\n",fd);close(fd);return 0;
}

执行结果:
open3


close函数

学会了open函数,这个函数就没什么好说的。很简单。直接上图。
close


read函数

还是先查man 2 read,直接上图。
read
其实这个函数也没啥好说的,和C语言的标库函数差不多。从一个文件中读取。

参数解读

  • 第一个fd就是上面我们在open中学的返回值,一个文件描述符,用来操作文件。
  • 第二个buf,就是缓冲区,用来接收从fd文件中读取的内容。
  • 第三个count,就是从文件中读取的字节数。

返回值

  • 如果读取成功,就返回读取到的字节数。
  • 如果返回0,不代表读取失败,而是表示读取到文件的末尾了。
  • 如果读取失败,返回-1,并且errno被设置。

特别提醒:每次读取文件的偏移量都会移动相应的读取的字节数。(原文是the file position is advanced by this number)


write函数

还是先查man 2 write,直接上图。
write
read差不多

参数解读

  • 第一个fd就是上面我们在open中学的返回值,一个文件描述符,用来操作文件。
  • 第二个buf,就是缓冲区,里面是要写入fd文件中的内容。
  • 第三个count,就是从文件中写入的字节数。

返回值

  • 如果写入成功,就返回写入到的字节数。
  • 如果写入失败,返回-1,并且errno被设置。

特别提醒:要写入文件时,一定打开相应的权限O_WRONLY,同时要确保当前用户有权限向文件写入(即该用户对该文件有w权限)


利用readwrite来实现cp功能

先来说一说思路,我们先打开被复制的文件,用fd1来表示它,再创建复制后的文件。用fd2来表示。每次都用readfd1读取,再直接用write写入fd2即可。
废话少说,直接上源代码:

#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>int main(int argc,char* argv[])
{int fd1,fd2,n;char buf[4096];fd1=open(argv[1],O_RDONLY);fd2=open(argv[2],O_RDWR | O_CREAT,0664);if(fd1<0 || fd2<0){printf("errno:%d:%s",errno,strerror(errno));exit(1);}while((n=read(fd1,buf,1024))!=0)write(fd2,buf,n);close(fd1);close(fd2);return 0;
}

效果如图
cp


预读入和缓输出

废话少说,先上图。
1


2
标准IO函数自带用户缓冲区,系统调用无用户级缓冲。可能上面的图各位童鞋看不懂,没关系,记住“系统函数并不是一定比库函数牛逼,能使用库函数的地方就使用库函数。


文件描述符

1
文件描述符的本质是指向文件结构体的指针。
PCB进程控制块:本质 结构体
成员: 文件描述符表。
文件描述符:0/1/2/3/4…/1023 表中可用的最小的。

0 - STDIN_FILENO
1 - STDOUT_FILENO
2 - STDERR_FILENO


lseek函数

还是先查看man 2 lseek
1

参数解读

  • fd应该很熟悉了吧,传要操作的文件。
  • offset是偏移量,就是你要文件移动的偏移量。
  • whence总共有三个值可以设定。SEEK_SET表示文件的开头,SEEK_CUR表示文件的当前的偏移量,SEEK_END表示文件的末尾。

返回值

返回值是个整数,表示当前文件的位置和开头的偏移量。

注意点

  1. 文件的“读”和“写”使用同一偏移量。
  2. 可以使用lseek获取大小
  3. 使用lseek拓展文件大小,但想真正引起文件大小变化,必须IO操作 。(这不是正规军的打法,正规军是应该是tuncate来拓展文件大小)

利用lseek获取文件大小

源代码:

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>int main(int argc,char* argv[])
{int fd,res;fd=open(argv[1],O_RDONLY);if(fd<0){perror("open file");exit(1);}res=lseek(fd,0,SEEK_END);printf("%s size is %d\n",argv[1],res);return 0;
}

效果:
2


目录项和 inode

1

一个文件主要由两部分组成,dentry(目录项)和 inode
inode 本质是结构体,存储文件的属性信息,如:权限、类型、大小、时间、用户、盘快位置…也叫做文件属性管理结构,大多数的 inode 都存储在磁盘上。少量常用、近期使用的inode 会被缓存到内存中。
所谓的删除文件,就是删除inode,但是数据其实还是在硬盘上,以后会覆盖掉。


stat 函数

还是先查看man 2 stat
1

参数解读

  • pathname看名字就知道是文件的路径。
  • statbuf这个参数类型是struct stat,虽然是第一次见,我这里简单介绍一下,包含文件各种信息的结构。

返回值

  • 成功返回0
  • 失败返回-1,errno被设置

关于struct stat

2

举例

源代码:

#include<unistd.h>
#include<stdio.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<stdlib.h>int main(int argc,char* argv[])
{struct stat sbf;stat(argv[1],&sbf);printf("The file size is %ld\n",sbf.st_size);if(S_ISREG(sbf.st_mode))printf("It is a regular file\n");else if (S_ISDIR(sbf.st_mode))printf("It is a directory\n");elseprintf("unkown file\n");return 0;
}

结果:
3


link函数和unlink函数

1

硬链接数就是 dentry 数目
link 就是用来创建硬链接的
link 可以用来实现 mv 命令

删除一个链接 int unlink(const char *pathname)

unlink 是删除一个文件的目录项 dentry,使硬链接数-1
unlink 函数的特征:清除文件时,如果文件的硬链接数到 0 了,没有 dentry 对应,但该文件仍不会
马上被释放,要等到所有打开文件的进程关闭该文件,系统才会挑时间将该文件释放掉。

由于这个函数比较简单,我这里就不赘述了。


目录操作函数

我这里就介绍三个最常用的函数:opendir readdir closedir
1


2
接下来我来用这几个函数来模拟实现Linux中的ls的功能来让具体体现这几个函数的用法


实现Linux的ls功能

源代码

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<string.h>
#include<dirent.h>void is_file(char*);void read_dir(char* dir)
{char path[256];DIR* dp;struct dirent* sdp;dp=opendir(dir);if(dp==NULL){perror("opendir error");return;}while((sdp=readdir(dp))!=NULL){if(strcmp(".",sdp->d_name)==0 || strcmp("..",sdp->d_name)==0)continue;sprintf(path,"%s/%s",dir,sdp->d_name);is_file(path);}closedir(dp);return;
}void is_file(char* name)
{int ret;struct stat sb;ret=stat(name,&sb);if(ret==-1){perror("stat error");return;}
}int main(int argc,char* argv[])
{if(argc==1)is_file(".");elseis_file(argv[1]);return 0;
}

效果展示
3


写在最后

个人亲身经验:我们学习的一系列Linux命令,一定要自己亲手去敲。不要只是看别人敲代码,不要只是停留在眼睛看,脑袋以为自己懂了,等你实际上手去敲会发现许许多多的这样那样的问题。正可谓“键盘敲烂,月薪过万


如果你觉得我写的题解还不错的,请各位王子公主移步到我的其他题解看看

  1. 数据结构与算法部分(还在更新中):
  • C++ STL总结 - 基于算法竞赛(强力推荐
  • 动态规划——01背包问题
  • 动态规划——完全背包问题
  • 动态规划——多重背包问题
  • 动态规划——分组背包问题
  • 动态规划——最长上升子序列(LIS)
  • 二叉树的中序遍历(三种方法)
  • 最长回文子串
  • 最短路算法——Dijkstra(C++实现)
  • 最短路算法———Bellman_Ford算法(C++实现)
  • 最短路算法———SPFA算法(C++实现)
  • 最小生成树算法———prim算法(C++实现)
  • 最小生成树算法———Kruskal算法(C++实现)
  • 染色法判断二分图(C++实现)
  1. Linux部分(还在更新中):
  • Linux学习之初识Linux
  • Linux学习之命令行基础操作
  • Linux学习之基础命令(适合小白)
  • Linux学习之权限管理和用户管理

✨🎉总结

“种一颗树最好的是十年前,其次就是现在”
所以,
“让我们一起努力吧,去奔赴更高更远的山海”
在这里插入图片描述
如果有错误❌,欢迎指正哟😋

🎉如果觉得收获满满,可以动动小手,点点赞👍,支持一下哟🎉

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/590548.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pandas教程(四)—— 分层索引及数据联合

1.分层索引 分层索引就是在一个轴上拥有多个&#xff08;两个及以上&#xff09;索引级别&#xff0c;能以低维度形式处理高维度数据。 行索引有两层 1.1 分层索引的创建 1.1.1 方式一&#xff1a;直接设置 1&#xff09;在创建series、dataframe或读取文件时时&#xff0c;行…

[蓝桥杯基础题型] 图论题目

遍历 添加路障 首先答案只能是0 1 2 &#xff0c;原因&#xff1a;把出发点堵住只需要两个路障 路障为0&#xff1a;不能找到一条从出发点到终点的路 路障为1&#xff1a;能找到一条从出发点到终点的路&#xff0c;但是只有一条 路障为2&#xff1a;能找到一条从出发点到终…

Linux搭建我的世界Mohist1.20.2版服务器教程,MOD和插件服开服教程,MC开服教程

雨云游戏云VPS服务器用Linux搭建MCSM面板和Minecraft Mohist 1.20.2服务器教程&#xff0c;我的世界MOD和插件服开服教程。 本教程演示安装的MC服是Mohist 1.20.2版&#xff0c;其他版本也可以参考本教程&#xff0c;差别不大。 本教程使用Docker来运行mc服&#xff0c;可以方…

【网络面试(5)】收发数据及断开服务器(四次挥手)

前面了解到服务器和客户端在创建套接字&#xff0c;建立连接后&#xff0c;就可以进入到下一步&#xff0c;双发可以互相发送和接收数据&#xff0c;本篇博客就来学习一下这个过程。  我们印象里&#xff0c;发送数据应该是我们在浏览器输入网址&#xff0c;敲击回车的一瞬间&…

NGUI基础-三大基础组件之Panel组件

目录 Panel组件 Panel的作用&#xff1a; 注意&#xff1a; 相关关键参数讲解&#xff1a; Alpha&#xff08;透明度值&#xff09;&#xff1a; Depth&#xff08;深度&#xff09;&#xff1a; Clippinng&#xff08;裁剪&#xff09;&#xff1a; ​编辑 None Tex…

Redis(Linux版本7.2.3)

1、停止Redis服务器 [roottssvr1-c1 sysconfig]# ps -ef | grep redis root 322 1 0 10月30 ? 02:58:53 ./bin/redis-server 0.0.0.0:6379 root 32664 12498 0 14:45 pts/0 00:00:00 grep --colorauto redis [roottssvr1-c1 sysconfig]# [roottssvr…

VMware虚拟机和Centos7镜像安装

文章目录 安装VMware虚拟机1、下载2、激活 安装Centos7镜像启动虚拟机 安装VMware虚拟机 1、下载 建议还是安装16版本 VMware16下载 https://www.123pan.com/s/HQeA-aX1Sh VMware15 链接&#xff1a;https://pan.baidu.com/s/11UD1hb6IydbxNNPxmh-MqA?pwd0630 提取码&am…

PiflowX组件-JDBCRead

JDBCRead组件 组件说明 使用JDBC驱动向任意类型的关系型数据库读取数据。 计算引擎 flink 有界性 Scan Source: Bounded Lookup Source: Sync Mode 组件分组 Jdbc 端口 Inport&#xff1a;默认端口 outport&#xff1a;默认端口 组件属性 名称展示名称默认值允许…

simulink代码生成(五)——SCI接受模块;如何将串口发送的数据显示在matlab中

首先&#xff0c;实现DSP28335的自收自发&#xff1b; 添加串口收发模块&#xff1b; 设置参数&#xff0c;根据硬件选择串口模块&#xff1a; 配置中断触发&#xff1b;SCIB的接收中断的CPU中断号为9&#xff0c;PIE级中断为3&#xff1b; 因此如下配置&#xff1b; 代码生成…

Hive06_基础查询

HIVE 查询语句 1 查询语句语法&#xff1a; SELECT [ALL | DISTINCT] select_expr, select_expr, ... FROM table_reference [WHERE where_condition] [GROUP BY col_list] [ORDER BY col_list] [CLUSTER BY col_list | [DISTRIBUTE BY col_list] [SORT BY col_list] ] [LIMI…

C++ 类和对象 (中)

默认成员函数&#xff1a; C环境下每一个类在定义是时编译器会自动生成六个成员函数&#xff08;在没有显示定义的情况下&#xff09;&#xff0c;分别是构造函数、析构函数、拷贝构造函数、赋值运算符重载、普通变量和const常量的取地址重载&#xff0c;它们大大弥补了原先C语…

QT上位机开发(图形绘制)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 图形绘制是上位机软件开发很重要的一个功能。这个图形绘制&#xff0c;有的是离线的&#xff0c;有的是实时绘制的。就我个人而言&#xff0c;离线…

JoySSL怎么样

JoySSL是一家专业的SSL证书服务提供商&#xff0c;致力于为网站和在线业务提供最佳的安全加密解决方案。以下是JoySSL的一些优点&#xff1a; 提供多种类型的SSL证书选择&#xff1a;JoySSL提供单域名、多域名、通配符等不同类型的SSL证书&#xff0c;以满足不同网站的需求。证…

【嵌入式】飞凌嵌入式ELF1开发板 初体验 | 嵌入式Linux开发

文章目录 前言一、开机初体验1.1、开机1.2、连接WIFI 二、基本功能测试2.1、主板命令行测试2.1.1、TF卡热插拔测试2.1.2、LED命令行测试2.1.3、数据库测试 三、基础编程实战3.1、交叉编译链部署3.2、温湿度传感器程序3.3、看门狗程序3.4、六轴传感器程序3.5、MQTT物联网 bug记录…

ROS TF坐标变换 - 动态坐标变换

目录 一、动态坐标变换&#xff08;C实现&#xff09;二、动态坐标变换&#xff08;Python实现&#xff09; 一、动态坐标变换&#xff08;C实现&#xff09; 所谓动态坐标变换&#xff0c;是指两个坐标系之间的相对位置是变化的。比如机械臂末端执行器与 base_link 之间&…

渗透线上下料控制(SCL源代码)

有关渗透线的其它详细介绍请参考下面链接文章&#xff1a; https://rxxw-control.blog.csdn.net/article/details/133611151https://rxxw-control.blog.csdn.net/article/details/133611151这里的渗透线上下料属于整个渗透线流程里的最前端和最后端&#xff0c;分别负责待处理…

《Linux系统与网络管理》复习题库---简答题

1、简述这些分区的名字以及各自的作用。 答&#xff1a; /boot 存放内核镜像的地方&#xff0c;这个文件夹独立分区的意义在于降低不能开机的风险。 /根目录&#xff0c;一般采用 ext3 文件系统&#xff0c;分区的容量一定要大于安装软件包的容量。 /usr 多数软件的默认安装的地…

Anaconda3 2021.11安装

1. 镜像下载&#xff1a;Index of /anaconda/archive/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 2. 安装在D盘&#xff1a; 3. 配置环境变量&#xff1a; 在这里&#xff0c;第一个教程A在系统变量里配置了五个&#xff0c;但我没有 所以又搜了教程B&#xf…

扎根底层技术,推动机器人换代式升级

热赛道和冷市场的矛盾之下&#xff0c;机器人需要一次换代式升级。 冷中有热的资本市场 在宏观经济下行的影响下&#xff0c;我国服务机器人产量从2022年开始出现明显放缓&#xff0c;2021年12月至2022年12月&#xff0c;我国服务机器人产量都处于同比下滑的状态&#xff0c;…

LeetCode每日一题.05(N皇后)

按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回所有不同的 n 皇后问题 的解决方案。 每一种…