《LINUX系統編程》筆記p3

可重用函數

不使用全局部變量,可以重復使用的函數.

stat 命令

作用:顯示一個文件或文件夾的“元信息”。

文件基本信息

  • 文件(File):顯示所查詢對象的名稱。

  • 大小(Size):文件的大小,以字節為單位。

  • 塊(Blocks):文件在磁盤上所占用的物理塊數量(通常以 512字節 或 1K 的塊為單位,取決于系統和 stat 的實現)。

  • IO 塊(IO Block):文件系統每次讀寫操作的數據塊大小。

  • 文件類型和索引節點(Inode)

    • 設備(Device):文件所在的設備標識符,通常以 主設備號,次設備號 的形式表示,指明了文件存儲在哪個硬件設備上。
    • Inode:文件的索引節點號。Inode 是文件系統中存儲文件元數據(除文件名外的一切信息)的數據結構。每個 Inode 號在同一個文件系統內是唯一的。
  • 文件類型(Filetype),例如:

    • 常規文件(regular file)
    • 目錄(directory)
    • 符號鏈接(symbolic link)
    • 塊設備(block device)
    • 字符設備(character device)
    • 套接字(socket)
    • 命名管道(FIFO)等。
  1. 權限和鏈接

    • 權限(Access):文件的訪問權限,以數字(八進制,如 0644) 和類似 ls -l 的符號(如 -rw-r--r--) 兩種形式顯示。
    • 硬鏈接數(Links):指向該 Inode 的硬鏈接數量。對于目錄,這個數字通常至少為 2(本身和其內部的 . 目錄)。
      所有權信息
      UID / GID:文件所有者的用戶ID(User ID)和組ID(Group ID)。
  2. 時間戳(Timestamps) - 這是 stat 命令最核心和詳細的信息之一 它提供了三個精確到納秒的時間戳,遠比其他命令詳細:

    • 訪問時間(Access):文件內容最后一次被讀取的時間(例如,
    • 修改時間(Modify):文件內容最后一次被修改的時間。
    • 變更時間(Change):文件的元數據(如權限、所有權、硬鏈接數等屬性)最后一次被改變的時間。

stat 命令格式

stat [文件或文件夾]

stat 函數

#include?<sys/types.h>
#include?<sys/stat.h>
#include?<unistd.h>// 使用文件路徑獲件的信息
int?stat(const?char?*pathname,?struct?stat *statbuf);// 使用文件描述符獲件的信息
int?fstat(int?fd,?struct?stat *statbuf);// lstat獲取軟鏈接文件本身的信息, stat獲取文件的信息
int?lstat(const?char?*pathname,?struct?stat *statbuf);

struct stat 結構體

struct?stat?{dev_t?????st_dev;?????????/* ID of device containing file 設備文件ID */ino_t?????st_ino;?????????/* Inode number 索引節點數*/mode_t????st_mode;????????/* File type and mode 文件類型和模式 , st_mode. 的文件類型等信息,詳見 inode(7):man 7 inode*/nlink_t???st_nlink;???????/* Number of hard links 硬連接數*/uid_t?????st_uid;?????????/* User ID of owner 擁有者ID*/gid_t?????st_gid;?????????/* Group ID of owner 擁有者組ID*/dev_t?????st_rdev;????????/* Device ID (if special file)  設備ID */off_t?????st_size;????????/* Total size, in bytes 文件大小*/blksize_t?st_blksize;?????/* Block size for filesystem I/O 每次IO 的塊大小 */blkcnt_t??st_blocks;??????/* Number of 512B blocks allocated 以 512 字節計算的塊數。*//* Since Linux 2.6, the kernel supports nanosecondprecision for the following timestamp fields.For the details before Linux 2.6, see NOTES. */struct?timespec?st_atim;??/* Time of last access 最后訪問時間*/struct?timespec?st_mtim;??/* Time of last modification 最后修改時間 */struct?timespec?st_ctim;??/* Time of last status change 最后元數據塊修改時間*/#define?st_atime st_atim.tv_sec??????/* Backward compatibility */
#define?st_mtime st_mtim.tv_sec
#define?st_ctime st_ctim.tv_sec
};

st_mode 的類型掩碼和值

// 類型掩碼(4bit)
S_IFMT     0170000   bit mask for the file type b
it field// 掩碼后的值:
S_IFSOCK   0140000   socket 套接字
S_IFLNK    0120000   symbolic link 符號鏈接
S_IFREG    0100000   regular file 普通文件
S_IFBLK    0060000   block device 塊文件
S_IFDIR    0040000   directory 文件夾
S_IFCHR    0020000   character device 字符設備文件
S_IFIFO    0010000   FIFO  管道文件
// 用法
strcut stat sb;
stat(pathname, &sb);
if ((sb.st_mode & S_IFMT) == S_IFREG) {/* Handle regular file */
}

判斷 st_mode 是哪一類型文件的宏定義

S_ISREG(m)  is it a regular file?
S_ISDIR(m)  directory?
S_ISCHR(m)  character device?
S_ISBLK(m)  block device?
S_ISFIFO(m) FIFO (named pipe)?
S_ISLNK(m)  symbolic     link?      (Not     inPOSIX.1-1996.)
S_ISSOCK(m) socket?  (Not in POSIX.1-1996.)
// 用法
struct stat sb;
stat(pathname, &sb);
if (S_ISREG(sb.st_mode)) {/* Handle regular file */
}

示例代碼:

#include?<time.h>int?main(int?argc,?char?* argv[])?{int?ret;struct?stat?st;ret = stat("homework01.c", &st);// ret = stat("./test", &st);printf("文件大小:%ld\n", st.st_size);printf("文件塊個數:%ld\n", st.st_blocks);printf("修改時間:%s\n", ctime(&st.st_mtim.tv_sec));// 判斷stat 的第一個參數是什么類型的文件。switch?(st.st_mode & S_IFMT) {?// man 7 inode 查找宏定義case?S_IFREG:printf("普通文件\n");break;case?S_IFDIR:printf("文件夾\n");break;default:printf("其他類型的文件\n");}printf("程序結束\n");return?0;
}

時間函數

#include?<time.h>// 將 struct tm 轉為時間字符串。
char?*asctime(const?struct?tm *tm);
char?*asctime_r(const?struct?tm *tm,?char?*buf);// 將 time_t 轉為時間字符串,格式: Fri Aug 22 09:40:48 2025。
char?*ctime(const?time_t?*timep);
char?*ctime_r(const?time_t?*timep,?char?*buf);

文件夾遍歷

// 打開文件夾
#include?<sys/types.h>
#include?<dirent.h>
DIR *opendir(const?char?*name);// 遍歷文件夾
#include?<dirent.h>
struct?dirent *readdir(DIR *dirp);// 關閉文件夾
#include?<sys/types.h>
#include?<dirent.h>
int?closedir(DIR *dirp);

示例

#include?<stdio.h>
#include?<sys/types.h>
#include?<dirent.h>int?main(int?argc,?char?* argv[])?{DIR *dir;struct?dirent?*curd;dir = opendir(".");while(curd = readdir(dir)) {// #define NULL ((void*)0)// printf("%p\n", curd);printf("curd->d_type:%#x, curd->d_name:%s\n",?curd->d_type, curd->d_name);}closedir(dir);printf("程序結束\n");return?0;
}

glob 函數查找文件

作用:使用模式匹配解析文件夾內容。

匹配樣式特殊字符

* 匹配0個一個或多個字符
? 匹配任意單個字符。
[a-z]  匹配一個某個范圍內的字符。
[xyz]  匹配一個字符,這個字符必須是 x 或 y 或 z
[^xyz]  匹配一個字符,這個字符不能是 x 或 y 或 z

相關函數

#include?<glob.h>// 獲取模式匹配的路徑信息,存入pglob。
int?glob(const?char?*pattern,?int?flags,int?(*errfunc) (const?char?*epath,?int?eerrno),glob_t?*pglob);
// 參數:
// pattern 路徑的樣式
// flags 搜索的標志位(位或可以加入多個選項):GLOB_NOSORT 表示不排序,
// errfunc 錯誤回調函數,不用時置空
// pglob 解析到的目錄個數以及各個文件名的數組。//釋放glob函數動態開辟的空間
void?globfree(glob_t?*pglob);// 類型:
glob_t?//存儲解析到的目錄個數以及各個文件名

glob_t 類型

?typedef?struct?{size_t???gl_pathc;????/* Count of paths matched so far  */char???**gl_pathv;????/* List of matched pathnames.  */size_t???gl_offs;?????/* Slots to reserve in gl_pathv.  */
}?glob_t;

示例:

#include?<stdio.h>
#include?<sys/types.h>
#include?<sys/stat.h>
#include?<unistd.h>
#include?<time.h>
#include?<sys/types.h>
#include?<dirent.h>
#include?<glob.h>// 搜索 /etc/pass* 或 當前的"*.c" 文件
int?main(int?argc,?char?* argv[])?{glob_t?gs;?// 用于存儲解析到的文件個數和文件名int?i;?// 循環變量int?ret;ret = glob("/etc/pass*", GLOB_NOSORT,?NULL, &gs);if?(ret) {printf("glob error:%d\n", ret);}ret = glob("./0[0-9]*.c", GLOB_APPEND,?NULL, &gs);// 循環打印遍歷的結果。for?(i =?0; i < gs.gl_pathc; i++) {printf("path: %s\n", gs.gl_pathv[i]);}// 釋放glob 開辟的內存空間。globfree(&gs);printf("程序結束\n");return?0;
}

getopt 函數

作用:解析命令行選項【option】和參數【argument】

函數格式

#include?<unistd.h>
int?getopt(int?argc,?char?*?const?argv[],?const?char?*optstring);

示例代碼

#include?<stdio.h>
#include?<sys/types.h>
#include?<sys/stat.h>
#include?<unistd.h>// 命令選項:?
//    -f <文件路徑>  文件路徑可以通過 optarg 全局變量獲取。
//    -c 創建?
//    -x 解壓縮
int?main(int?argc,?char?* argv[])?{const?char?* optstring =?"cxf:";int?ret;??//用于接收返回的命令選項while?(1) {ret = getopt(argc, argv, optstring);if?(ret ==?-1) {??// 解析完畢break;?// 結束循環}switch(ret) {case?'x':?printf("-x 選項被輸入\n");break;case?'c':?printf("-c 選項被輸入\n");break;case?'f':?printf("-f  選項: %s\n", optarg);break;default:break;}}printf("程序結束\n");return?0;
}

密碼加密

Linux 下保存密碼的文件是:/etc/shadow

easthome 的密碼信息:

easthome:$6$ISBgRfwrvZNBigDh$ynkvsffzGH2ovijtzar9CUiu37cTfx0SJcSs.TYWsXyVoJb1xFfmQX.PDyx5B0eU7mNZf0umcPI0ZvmpDf/dR/:20290:0:99999:7:::$6$ISBgRfwrvZNBigDh$ynkvsffzGH2ovijtzar9CUiu37cTfx0SJcSs.TYWsXyVoJb1xFfmQX.PDyx5B0eU7mNZf0umcPI0ZvmpDf/dR/

實現用戶登陸之前的密碼校驗:

相關函數

// 獲取密碼函數
#include?<unistd.h>
char?*getpass(const?char?*prompt);// 根據加密算法和鹽信息加密字符串?
// 使用 crypt 函數在編譯時需要加載 libcrypt 庫。 gcc -lcrypt
#include?<crypt.h>
char?*?crypt(const?char?*phrase,?const?char?*setting);
// 參數:?
//    phrase: 要加密的信息。
//    setting 加密算法和鹽信息,格式為 "$加密算法$鹽$"
// 返回值:
//    加密后的哈希字符串。// 讀取/etc/shadow 密碼信息
#include?<shadow.h>
struct?spwd *getspnam(const?char?*name);??// name 是用戶名。
// 參數:
//     name 用戶名
// 返回值:
//     shadow 中的加密算法、鹽、和哈希字符串。

示例代碼

#include?<stdio.h>
#include?<sys/types.h>
#include?<sys/stat.h>
#include?<unistd.h>
#include?<shadow.h>
#include?<crypt.h>
#include?<string.h>#define?MAX_NAME_SIZE (20)int?main(int?argc,?char?* argv[])?{char?username[MAX_NAME_SIZE] = {};?// 用于存儲用戶名.char?* pwd =?NULL;?// 用于指向用戶輸入的密碼。struct?spwd?*?tp?=?NULL;?// 指向shadow文件中讀出的信息。char?* serial =?NULL;?// 事項加密后的哈希值(密碼)。printf("請輸入用戶名:");fflush(stdout);int?ret = read(0, username, MAX_NAME_SIZE);//int ret = fgets(username, MAX_NAME_SIZE, stdin);  // 此函數會讀取回車符號username[ret-1] =?'\0';?// 把 '\n' 替換成  '\0';// 讀取密碼pwd = getpass("請輸入密碼:");if?(NULL?== pwd) {perror("getpass");return?-1;}?// printf("username:%s, password:%s\n", username, pwd);// 讀取系統內/etc/shadow真實的密碼信息tp = getspnam(username);if?(NULL?== tp) {printf("獲取shadow 密碼失敗\n");return?-2;}//將輸入的密碼進行加密serial = crypt(pwd, tp->sp_pwdp);?// 使用加密算法和鹽進行加密。if?(NULL?== serial) {perror("crypt");return?-3;}?//對比生成的 serial 和 tp->sp_pwdp 是否相同。如果相同說明驗證成功。if?(0?==?strcmp(tp->sp_pwdp, serial)) {printf("登陸成功\n");}?else?{printf("登陸失敗\n");}printf("程序結束\n");return?0;
}

編譯(加?-lcrypt?選項):

gcc?05_check_password.c -lcrypt

字符串分割

strtok 函數

作用:分割字符串

調用格式

#include?<string.h>
char?*strtok(char?*str,?const?char?*delim);
// 參數:
//   str 需要分割的字符串,第一次需要傳入可變字符串,之后需要傳入NULL
//   delim 分割的字符串
// 返回值: 返回分割的子字符串的起始地址,到達末尾時返回NULL。

字符串的內容:

"zhangsan,18,100"

示例代碼

#include?<stdio.h>
#include?<string.h>// 分割字符串示例;
int?main(int?argc,?char?* argv[])?{char?buffer[] =?"zhangsan,18,100,1.73";char?* str_head = buffer;?//將str_head指向字符串的首地址char?* str_ret;while(1) {str_ret = strtok(str_head,?",");?if?(NULL?== str_ret)break;printf("str_ret:%s\n", str_ret);str_head =?NULL;}// str_ret = strtok(str_head, ",");?// printf("str_ret:%s\n", str_ret);// str_ret = strtok(NULL, ",");?// printf("str_ret:%s\n", str_ret);// str_ret = strtok(NULL, ",");?// printf("str_ret:%s\n", str_ret);printf("程序結束\n");return?0;
}

strsep 函數

調用格式

#include?<string.h>
char?*strsep(char?**stringp,?const?char?*delim);
// 參數
//   stringp 是指向字符串指針的地址。
//   delim 分割的字符串
// 返回值: 返回子字符串的起始地址,即*stringp。到達末尾時返回NULL。

示例代碼

#include?<stdio.h>
#include?<string.h>// 分割字符串示例;
int?main(int?argc,?char?* argv[])?{char?buffer[] =?"zhangsan,18,100,1.73";char?* str_head = buffer;?//將str_head指向字符串的首地址char?* str_ret;while(1) {str_ret = strsep(&str_head,?",");?if?(NULL?== str_ret)break;printf("str_ret:%s\n", str_ret);}// str_ret = strsep(&str_head, ",");// printf("str_ret:%s\n", str_ret);// str_ret = strsep(&str_head, ",");// printf("str_ret:%s\n", str_ret);// str_ret = strsep(&str_head, ",");// printf("str_ret:%s\n", str_ret);printf("程序結束\n");return?0;
}

常量字符串不能用于上述兩個函數。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/94263.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/94263.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/94263.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

大模型0基礎開發入門與實踐:第3章 機器的“統計學”:機器學習基礎概念掃盲

第3章 機器的“統計學”&#xff1a;機器學習基礎概念掃盲 1. 引言 想象一下&#xff0c;你是一位古代的農夫&#xff0c;畢生的經驗告訴你&#xff1a;烏云密布、燕子低飛&#xff0c;那么不久便會下雨。你并沒有學習過氣象學&#xff0c;也不懂大氣壓和水汽凝結的原理。你的“…

Java調用Ollama(curl方式)

1. 安裝Ollama Search 2. 調用 相關依賴 <dependencies><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.14</version></dependency><dependency>&…

nodejs koa框架使用

1: KOA 是express 打造的下一代web 開發框架提供更小更強的的核心功能&#xff0c;通過Promise 、async/await 進行異步編程&#xff0c;koa 可以不使用回調&#xff0c;解決了回調地獄的問題 blueBird 是nodejs 最出名的Primise 實現&#xff0c;除了實現標準的promise 之外&a…

2025年圖像處理與光學國際會議(ICIPO 2025)

2025年圖像處理與光學國際會議&#xff08;ICIPO 2025&#xff09; 2025 International Conference on Image Processing and Optics一、大會信息會議簡稱&#xff1a;ICIPO 2025 大會地點&#xff1a;中國北京 審稿通知&#xff1a;投稿后2-3日內通知 投稿郵箱&#xff1a;iac…

Kubernetes 構建高可用、高性能 Redis 集群

k8s下搭建Redis高可用1. 部署redis服務創建ConfigMap創建 Redis創建 k8s 集群外部2. 創建 Redis 集群自動創建 redis 集群手動創建 redis 集群驗證集群狀態3. 集群功能測試壓力測試故障切換測試4. 安裝管理客戶端編輯資源清單部署 RedisInsight控制臺初始化控制臺概覽實戰環境使…

文件IO的基礎操作

Java針對文件進行的操作:文件系統操作,File類(file類指定的路徑,可以是一個不存在的文件)文件內容操作 : 流對象分為兩類(1)字節流 以字節為基本的讀寫單位的 二進制文件 InputStream OutputStream(2)字符流 以字符為基本的讀寫單位的 …

【模版匹配】基于深度學習

基于深度學習的模版匹配 概述 本報告整理了2024-2025年最新的、可直接使用的模板匹配相關論文、方法和開源代碼實現。所有方法都提供了完整的代碼實現和預訓練模型&#xff0c;可以直接應用到實際項目中。 一、輕量級現代模板匹配框架 1.1 UMatcher - 4M參數的緊湊型模板匹…

CMake進階:Ninja環境搭建與加速項目構建

目錄 1.引入Ninja的原因 2.Ninja 環境搭建&#xff08;跨平臺&#xff09; 2.1.Linux系統安裝 2.2.macOS 系統 2.3.Windows 系統 2.4.源碼編譯安裝&#xff08;通用方案&#xff09; 3.Ninja 與構建系統配合&#xff1a;以 CMake 為例 4.加速構建的關鍵技巧 5.Ninja 與…

開發避坑指南(35):mybaits if標簽test條件判斷等號=解析異常解決方案

異常信息 org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: The expression orderInfo.idList evaluated to a null value.報錯語句 <if test"orderInfo.queryFlag ! null and orderInfo.queryFlag sett…

GitCode 疑難問題診療:全面指南與解決方案

引言 在軟件開發的動態領域中&#xff0c;GitCode 作為一款強大的分布式版本控制系統&#xff0c;已然成為團隊協作與項目管理的基石。它賦予開發者高效管理代碼版本、輕松實現并行開發以及順暢協同合作的能力。然而&#xff0c;如同任何復雜的技術工具&#xff0c;在 GitCode…

使用 JS 渲染頁面并導出為PDF 常見問題與修復

本文直擊兩個最常見的導出痛點&#xff0c;并給出可直接落地的診斷 修復方案&#xff08;適用于 html2canvas jsPDF ECharts/自繪 canvas 場景&#xff09;。 問題清單 問題 A&#xff1a;導出后圖表模糊&#xff0c;線條與文字不清晰&#xff08;低分辨率&#xff09;。問題…

【Java后端】【可直接落地的 Redis 分布式鎖實現】

可直接落地的 Redis 分布式鎖實現&#xff1a;包含最小可用版、生產可用版&#xff08;帶 Lua 原子解鎖、續期“看門狗”、自旋等待、可重入&#xff09;、以及基于注解AOP 的無侵入用法&#xff0c;最后還給出 Redisson 方案對比與踩坑清單。一、設計目標與約束 獲取鎖&#x…

數據結構 -- 鏈表--雙向鏈表的特點、操作函數

雙向鏈表的操作函數DouLink.c#include "DouLink.h" #include <stdio.h> #include <stdlib.h> #include <string.h>/*** brief 創建一個空的雙向鏈表* * 動態分配雙向鏈表管理結構的內存&#xff0c;并初始化頭指針和節點計數* * return 成功返回指…

Wireshark獲取數據傳輸的碼元速率

一、Wireshark的物理層參數 Wireshark主界面可以看到數據發送時刻和長度&#xff1a; 這個時刻是Wireshark完整獲取數據包的時刻&#xff0c;實際上就是結束時刻。 需要知道的是&#xff1a; Wireshark工作在數據鏈路層及以上&#xff0c;它能解碼 以太網幀 / IP 包 / TCP…

11.1.3 完善注冊登錄,實現文件上傳和展示

1、完善注冊/登錄 1. 涉及的數據庫表單&#xff1a;user_info 2. 引用MySQL線程池&#xff0c;Redis線程池 3. 完善注冊功能 4. 完善登錄功能 2.1 涉及的數據庫表單&#xff1a;user_info 重新創建數據庫 #創建數據庫 DROP DATABASE IF EXISTS 0voice_tuchuang;CREATE D…

【Linux文件系統】目錄結構

有沒有剛進入Linux世界時&#xff0c;對著黑乎乎的終端&#xff0c;輸入一個 ls / 后&#xff0c;看著蹦出來的一堆名字 like bin, etc, usr&#xff0c;感覺一頭霧水&#xff0c;像是在看天書&#xff1f; 別擔心&#xff0c;你不是一個人。Linux的文件系統就像一個超級有條理…

螺旋槽曲面方程的數學建模與偏導數求解

螺旋槽曲面的數學描述 在鉆頭設計和機械加工領域,螺旋槽的幾何建模至關重要。螺旋槽通常由徑向截形繞軸做螺旋運動形成,其數學模型可通過參數方程和隱函數方程兩種方式描述。 設螺旋槽的徑向截形方程為: y=f(z)y = f(z)y=f(z) x=xcx = x_cx=xc? 其中 xcx_cxc? 為常數,…

線性回歸:機器學習中的基石

在機器學習的眾多算法中&#xff0c;線性回歸無疑是最基礎也是最常被提及的一種。它不僅在統計學中占有重要地位&#xff0c;而且在預測分析和數據建模中也發揮著關鍵作用。本文將深入探討線性回歸的基本概念、評估指標以及在實際問題中的應用&#xff0c;并通過一個模擬的氣象…

編程刷題-資料分發1 圖論/DFS

P2097 資料分發 1 題目描述 有一些電腦&#xff0c;一部分電腦有雙向數據線連接。 如果一個電腦得到數據&#xff0c;它可以傳送到的電腦都可以得到數據。 現在&#xff0c;你有這個數據&#xff0c;問你至少將其輸入幾臺電腦&#xff0c;才能使所有電腦得到數據。 輸入格式 第…

RabbitMQ:延時消息(死信交換機、延遲消息插件)

目錄一、死信交換機【不推薦】二、延遲消息插件【推薦】2.1 安裝插件【Linux】2.2 安裝插件【Windows】2.3 如何使用延時消息&#xff1a;生產者發送消息時指定一個時間&#xff0c;消費者不會立刻收到消息&#xff0c;而是在指定時間之后才收到消息。 延時任務&#xff1a;設置…