redis源碼剖析(七)—— Redis 數據結構dict.c

文章目錄

    • dict.h
  • dict.c

dict.h


//定義錯誤相關的碼
#define DICT_OK 0
#define DICT_ERR 1//實際存放數據的地方
typedef struct dictEntry {void *key;void *val;struct dictEntry *next;
} dictEntry;//哈希表的定義
typedef struct dict {//指向實際的哈希表記錄(用數組+開鏈的形式進行保存)dictEntry **table;//type中包含一系列哈希表需要用到的函數dictType *type;//size表示哈希表的大小,為2的指數unsigned long size;//sizemask=size-1,方便哈希值根據size取模unsigned long sizemask;//used記錄了哈希表中有多少記錄unsigned long used;void *privdata;
} dict;//對Hash表進行迭代遍歷時使用的迭代器
typedef struct dictIterator {dict *ht;int index;dictEntry *entry, *nextEntry;
} dictIterator;/* This is the initial size of every hash table */
//每個Hash表的初始大小
#define DICT_HT_INITIAL_SIZE     4

dict.c

#include "fmacros.h"#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
#include <limits.h>#include "dict.h"
#include "zmalloc.h"/* ---------------------------- Utility funcitons --------------------------- *//*** 打印出系統的崩潰信息* C語言中的可變參數的使用va_start va_end*/
static void _dictPanic(const char *fmt, ...)
{va_list ap;va_start(ap, fmt);fprintf(stderr, "\nDICT LIBRARY PANIC: ");vfprintf(stderr, fmt, ap);fprintf(stderr, "\n\n");va_end(ap);
}/* ------------------------- Heap Management Wrappers------------------------ */
/** *  堆分配函數*/
static void *_dictAlloc(size_t size)
{void *p = zmalloc(size);if (p == NULL)_dictPanic("Out of memory");return p;
}/*** 堆釋放函數*/
static void _dictFree(void *ptr) {zfree(ptr);
}/* -------------------------- private prototypes ---------------------------- */static int _dictExpandIfNeeded(dict *ht);
static unsigned long _dictNextPower(unsigned long size);
static int _dictKeyIndex(dict *ht, const void *key);
static int _dictInit(dict *ht, dictType *type, void *privDataPtr);/* -------------------------- hash functions -------------------------------- *//* Thomas Wang's 32 bit Mix Function */
/*** 求Hash的鍵值,可以促使均勻分布*/
unsigned int dictIntHashFunction(unsigned int key)
{key += ~(key << 15);key ^=  (key >> 10);key +=  (key << 3);key ^=  (key >> 6);key += ~(key << 11);key ^=  (key >> 16);return key;
}/*** 直接將整數key作為Hash的鍵值*/
/* Identity hash function for integer keys */
unsigned int dictIdentityHashFunction(unsigned int key)
{return key;
}/* Generic hash function (a popular one from Bernstein).* I tested a few and this was the best. */
//Hash函數(通用目的Hash函數)
unsigned int dictGenHashFunction(const unsigned char *buf, int len) {unsigned int hash = 5381;while (len--)hash = ((hash << 5) + hash) + (*buf++); /* hash * 33 + c */return hash;
}/* ----------------------------- API implementation ------------------------- *//* Reset an hashtable already initialized with ht_init().* NOTE: This function should only called by ht_destroy(). */
/*** 重設Hash表* 各種值都設置為0*/
static void _dictReset(dict *ht)
{ht->table = NULL;ht->size = 0;ht->sizemask = 0;ht->used = 0;
}/*** 創建一個新的Hash表* type為可用于Hash表上面的相應函數*/
/* Create a new hash table */
dict *dictCreate(dictType *type,void *privDataPtr)
{dict *ht = _dictAlloc(sizeof(*ht));_dictInit(ht,type,privDataPtr);return ht;
}/* Initialize the hash table */
/*** 初始化Hash表*/
int _dictInit(dict *ht, dictType *type,void *privDataPtr)
{//對Hash表進行初始化_dictReset(ht);//初始化能夠作用于Hash中的相應函數集ht->type = type;//初始化hashtable的私有數據段ht->privdata = privDataPtr;//返回初始化成功return DICT_OK;
}/* Resize the table to the minimal size that contains all the elements,* but with the invariant of a USER/BUCKETS ration near to <= 1 *//*** DICT_HT_INITIAL_SIZE=4表示的是Hash表的初始大小* 重新調整Hash表的大小* 從這里可以看出Hash表的最小的大注為4*/
int dictResize(dict *ht)
{int minimal = ht->used;if (minimal < DICT_HT_INITIAL_SIZE)minimal = DICT_HT_INITIAL_SIZE;return dictExpand(ht, minimal);
}/* Expand or create the hashtable */
/*** 創建Hash表,Hash表的大小為size*/
int dictExpand(dict *ht, unsigned long size)
{dict n; /* the new hashtable *///重設Hash表的大小,大小為2的指數unsigned long realsize = _dictNextPower(size);/* the size is invalid if it is smaller than the number of* elements already inside the hashtable *///如果大小比當原Hash表中記錄數目還要小的話,則出錯if (ht->used > size)return DICT_ERR;//初始化_dictInit(&n, ht->type, ht->privdata);n.size = realsize;//保證為素數n.sizemask = realsize-1;n.table = _dictAlloc(realsize*sizeof(dictEntry*));/* Initialize all the pointers to NULL *///將所有的指針初始為空memset(n.table, 0, realsize*sizeof(dictEntry*));/* Copy all the elements from the old to the new table:* note that if the old hash table is empty ht->size is zero,* so dictExpand just creates an hash table.* *///使用的內存記錄數n.used = ht->used;int i;for (i = 0; i < ht->size && ht->used > 0; i++) {dictEntry *he, *nextHe;if (ht->table[i] == NULL) continue;//采用的是桶狀鏈表形式/* For each hash entry on this slot... */he = ht->table[i];//在遍歷的過程中對每一個元素又求取出在新Hash表中相應的位置 while(he) {unsigned int h;nextHe = he->next;/* Get the new element index *///dictHashKey(ht,he->key)獲取相應的鍵值key,實際上就是取模運算//求取在新hash表中的元素的位置h = dictHashKey(ht, he->key) & n.sizemask;//采用的是頭插入法進行的插入he->next = n.table[h];n.table[h] = he;ht->used--;/* Pass to the next element */he = nextHe;}}//斷言原Hash表中已經沒有記錄了assert(ht->used == 0);//將原Hash表進行釋放 _dictFree(ht->table);/* Remap the new hashtable in the old *///將新Hash表作為值進行賦值*ht = n;//返回創建成功return DICT_OK;
}/* Add an element to the target hash table */
/*** 向Hash表中增加元素* 增加元素的鍵為key,值為vals*/
int dictAdd(dict *ht, void *key, void *val)
{int index;dictEntry *entry;/* Get the index of the new element, or -1 if* the element already exists. */if ((index = _dictKeyIndex(ht, key)) == -1)return DICT_ERR;/* Allocates the memory and stores key *///分配內存空間entry = _dictAlloc(sizeof(*entry));//將其放入相應的slot里面//采用的是頭插入法進行插入entry->next = ht->table[index];ht->table[index] = entry;/* Set the hash entry fields. */dictSetHashKey(ht, entry, key);dictSetHashVal(ht, entry, val);//使用的記錄數進行+1操作ht->used++;//返回OK標記return DICT_OK;
}/* Add an element, discarding the old if the key already exists */
//向hash表中增加一個元素,如果Hash表中已經有該元素的話
//則將該元素進行替換掉
int dictReplace(dict *ht, void *key, void *val)
{dictEntry *entry;/* Try to add the element. If the key* does not exists dictAdd will suceed. */if (dictAdd(ht, key, val) == DICT_OK)return DICT_OK;/* It already exists, get the entry *///如果已經存在的話,則獲取相應的位置 entry = dictFind(ht, key);/* Free the old value and set the new one *///將原Hash表中該entry的值進行釋放//避免內存泄露dictFreeEntryVal(ht, entry);//給該節點設置新值dictSetHashVal(ht, entry, val);//返回成功標記return DICT_OK;
}/*** 從Hash表中刪除指定的key*/
/* Search and remove an element */
static int dictGenericDelete(dict *ht, const void *key, int nofree)
{unsigned int h;dictEntry *he, *prevHe;if (ht->size == 0)return DICT_ERR;/***  返回key對應的dictEntry*/h = dictHashKey(ht, key) & ht->sizemask;he = ht->table[h];prevHe = NULL;while(he) {if (dictCompareHashKeys(ht, key, he->key)) {/* Unlink the element from the list */if (prevHe)prevHe->next = he->next;elseht->table[h] = he->next;if (!nofree) {//如果需要釋放的情況下,則進行相應的釋放操作dictFreeEntryKey(ht, he);dictFreeEntryVal(ht, he);}_dictFree(he);//記錄數相應的進行減小ht->used--;return DICT_OK;}//進行相應的賦值操作prevHe = he;he = he->next;}//返回錯誤return DICT_ERR; /* not found */
}/*** 釋放指定的鍵值*/
int dictDelete(dict *ht, const void *key) {return dictGenericDelete(ht,key,0);
}/*** 從Hash表中刪除key對應的記錄,但是不* 刪除相應的key以及value*/
int dictDeleteNoFree(dict *ht, const void *key) {return dictGenericDelete(ht,key,1);
}/* Destroy an entire hash table */
/*** 釋放整個Hash表*/
int _dictClear(dict *ht)
{unsigned long i;/* Free all the elements *//*** 將所有的元素進行釋放 */for (i = 0; i < ht->size && ht->used > 0; i++) {dictEntry *he, *nextHe;//表標桶狀結構中沒有鏈表元素if ((he = ht->table[i]) == NULL) continue;//循環進行遍歷while(he) {nextHe = he->next;//釋放鍵dictFreeEntryKey(ht, he);//釋放值 dictFreeEntryVal(ht, he);//釋放結構體_dictFree(he);//記錄數作相應的減法ht->used--;he = nextHe;}}/* Free the table and the allocated cache structure *///釋放整個Hash表_dictFree(ht->table);/* Re-initialize the table *///重新初始化整個Hash表,Hash結構還是要保留的_dictReset(ht);return DICT_OK; /* never fails */
}/* Clear & Release the hash table */
/*** 釋放Hash表* 整個Hash表連同Hash結構都將釋放 */
void dictRelease(dict *ht)
{//清除Hash表中的數據_dictClear(ht);//對空間進行釋放 _dictFree(ht);
}/***  從HashTable中查找key的相應的dictEntry*/
dictEntry *dictFind(dict *ht, const void *key)
{dictEntry *he;unsigned int h;//如果Hash表的大小為0,則直接返回NULLif (ht->size == 0) return NULL;h = dictHashKey(ht, key) & ht->sizemask;he = ht->table[h];while(he) {if (dictCompareHashKeys(ht, key, he->key))return he;he = he->next;}return NULL;
}/** * 獲取Hash表中的相應的迭代器*/
dictIterator *dictGetIterator(dict *ht)
{//給迭代器分配內存空間dictIterator *iter = _dictAlloc(sizeof(*iter));//對迭代器進行相應的初始化iter->ht = ht;iter->index = -1;iter->entry = NULL;iter->nextEntry = NULL;return iter;
}/*** 對Hashtable進行迭代遍歷操作*/
dictEntry *dictNext(dictIterator *iter)
{while (1) {if (iter->entry == NULL) {iter->index++;//如果遍歷的index大于整個Hashtable數組的大小時//說明已經遍歷完成,直接跳出if (iter->index >=(signed)iter->ht->size) break;iter->entry = iter->ht->table[iter->index];} else {//遍歷到下一個元素iter->entry = iter->nextEntry;}if (iter->entry) {/* We need to save the 'next' here, the iterator user* may delete the entry we are returning. *///返回遍歷過程中的下一個元素iter->nextEntry = iter->entry->next;//返回當前遍歷的元素return iter->entry;}}return NULL;
}/*** 釋放迭代器把指向的空間*/
void dictReleaseIterator(dictIterator *iter)
{_dictFree(iter);
}/* Return a random entry from the hash table. Useful to* implement randomized algorithms */
/*** 從Hashtable中獲取隨機的key*/
dictEntry *dictGetRandomKey(dict *ht)
{dictEntry *he;unsigned int h;int listlen, listele;//如果整個HashTable中壓根沒有記錄時//直接返回NULLif (ht->used == 0) return NULL;//否則隨機選擇一個HashTable里面的slotdo {h = random() & ht->sizemask;he = ht->table[h];} while(he == NULL);/* Now we found a non empty bucket, but it is a linked* list and we need to get a random element from the list.* The only sane way to do so is to count the element and* select a random index. *///計算出處于這個slot里面的元素數目listlen = 0;while(he) {he = he->next;listlen++;}//從整個slot鏈表中選擇元素的位置listele = random() % listlen;he = ht->table[h];//指針指向該鏈表的位置 while(listele--) he = he->next;return he;
}/* ------------------------- private functions ------------------------------ *//* Expand the hash table if needed */
/*** 判斷Hash表的大小是否需要擴充*/
static int _dictExpandIfNeeded(dict *ht)
{/* If the hash table is empty expand it to the intial size,* if the table is "full" dobule its size. *///如果目前的hashtable的大小為0,則將大小設置為4if (ht->size == 0)return dictExpand(ht, DICT_HT_INITIAL_SIZE);//如果hash表里數據記錄數已經與hashtable的大小相同的話,則將大小擴充為2倍if (ht->used == ht->size)//里面的記錄數已經達到了hashtable的大小時,則需要進行擴充空間return dictExpand(ht, ht->size*2);return DICT_OK;
}/* Our hash table capability is a power of two */
/*** Hash表的大小為2的指數冪*/
static unsigned long _dictNextPower(unsigned long size)
{//將i設置為hash表的初始大小即為4unsigned long i = DICT_HT_INITIAL_SIZE;//返回2的指數冪中與size大小最接近且比size大小的值if (size >= LONG_MAX) return LONG_MAX;while(1) {if (i >= size)return i;//i *= 2;}
}/* Returns the index of a free slot that can be populated with* an hash entry for the given 'key'.* If the key already exists, -1 is returned. */
/*** 返回key在hash表的位置,如果key在Hash表里已經存在,* 則返回-1*/
static int _dictKeyIndex(dict *ht, const void *key)
{unsigned int h;dictEntry *he;/*** 判斷是否需要擴充Hash表*//* Expand the hashtable if needed */if (_dictExpandIfNeeded(ht) == DICT_ERR)return -1;/* Compute the key hash value *//*** 獲取Hash表中key對應元素位置【即Hash表中的位置】 */h = dictHashKey(ht, key) & ht->sizemask;/* Search if this slot does not already contain the given key */he = ht->table[h];while(he) {//如果已經存在了話,即鍵值相等的話if (dictCompareHashKeys(ht, key, he->key))return -1;he = he->next;}//否則的話,就返回相應的slot位置 return h;
}/*** 清空HashTable* 清空后HashTable進行了重新的初始化*/
void dictEmpty(dict *ht) {_dictClear(ht);
}/*** 打印出HashTable表中數據的當前狀態* maxchainlen最大鏈表的長度* chainlen* slot表示Hashtable中已使用的桶數*/
#define DICT_STATS_VECTLEN 50
void dictPrintStats(dict *ht) {unsigned long i, slots = 0, chainlen, maxchainlen = 0;unsigned long totchainlen = 0;unsigned long clvector[DICT_STATS_VECTLEN];//如果Hashtable中為0記錄數,則打印出空Hashtableif (ht->used == 0) {printf("No stats available for empty dictionaries\n");return;}//對clvector數組進行相應的初始化for (i = 0; i < DICT_STATS_VECTLEN; i++) clvector[i] = 0;for (i = 0; i < ht->size; i++) {dictEntry *he;if (ht->table[i] == NULL) {//從這里可以看出clvector[0]記錄Hashtable中的空槽數clvector[0]++;continue;}//否則的知槽數++slots++;/* For each hash entry on this slot... */chainlen = 0;he = ht->table[i];//算出槽中的鏈表長度while(he) {chainlen++;he = he->next;}//如果小于50的話,則clvector相應的記錄增加//例如clvector[2]=10,表示Hashtable中槽里面鏈表長度為2的有10個//超過50的全部放在clvector[49]里面clvector[(chainlen < DICT_STATS_VECTLEN) ? chainlen : (DICT_STATS_VECTLEN-1)]++;if (chainlen > maxchainlen) maxchainlen = chainlen;totchainlen += chainlen;}//將狀態信息打印出來printf("Hash table stats:\n");//hashtable的大小printf(" table size: %ld\n", ht->size);//hashtable中存在的記錄數printf(" number of elements: %ld\n", ht->used);//hashtalbe中已使用的槽數printf(" different slots: %ld\n", slots);//hashtable中最大鍵的長度printf(" max chain length: %ld\n", maxchainlen);//hashtable中平均鏈表的長度printf(" avg chain length (counted): %.02f\n", (float)totchainlen/slots);//和上一個值理論上來講應該是一樣的printf(" avg chain length (computed): %.02f\n", (float)ht->used/slots);printf(" Chain length distribution:\n");//打印出鏈表中的各個槽里面的鏈表的長度記錄for (i = 0; i < DICT_STATS_VECTLEN-1; i++) {if (clvector[i] == 0) continue;printf("   %s%ld: %ld (%.02f%%)\n",(i == DICT_STATS_VECTLEN-1)?">= ":"", i, clvector[i], ((float)clvector[i]/ht->size)*100);}
}/* ----------------------- StringCopy Hash Table Type ------------------------*//*** Hash函數(字符串復制相關的Hash表函數)*/
static unsigned int _dictStringCopyHTHashFunction(const void *key)
{return dictGenHashFunction(key, strlen(key));
}
/*** 鍵值復制相關的函數*/
static void *_dictStringCopyHTKeyDup(void *privdata, const void *key)
{int len = strlen(key);char *copy = _dictAlloc(len+1);/*** #define DICT_NOTUSED(V) ((void) V);*/DICT_NOTUSED(privdata);//進行鍵值的復制操作memcpy(copy, key, len);//在字符串未尾加了\0標識字符串的結束copy[len] = '\0';return copy;
}/*** HashTable中值復制操作*/
static void *_dictStringKeyValCopyHTValDup(void *privdata, const void *val)
{  //獲取值的長度int len = strlen(val);//分配內存空間char *copy = _dictAlloc(len+1);DICT_NOTUSED(privdata);//進行內存復制的操作memcpy(copy, val, len);copy[len] = '\0';return copy;
}/*** 鍵值的比較函數* 比較key1與key2的值是否相等*/
static int _dictStringCopyHTKeyCompare(void *privdata, const void *key1,const void *key2)
{DICT_NOTUSED(privdata);return strcmp(key1, key2) == 0;
}/*** HashTable的析構函數*/
static void _dictStringCopyHTKeyDestructor(void *privdata, void *key)
{DICT_NOTUSED(privdata);//釋放key所占用的內存空間_dictFree((void*)key); /* ATTENTION: const cast */
}/*** HashTable中釋放值*/
static void _dictStringKeyValCopyHTValDestructor(void *privdata, void *val)
{DICT_NOTUSED(privdata);//釋放值所占用的內存空間_dictFree((void*)val); /* ATTENTION: const cast */
}

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

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

相關文章

簡述linux中動態庫和靜態庫的制作調用流程

假設現在有這些文件&#xff1a;sub.c add.c div.c mul.c mainc head.h&#xff08;前4個.C文件的頭文件&#xff09; 1.靜態庫制作流程 gcc -c sub.c add.c div.c mul.c -->生成 .o目標文件文件 ar rcs libmycal.a *.o …

redis源碼剖析(八)—— 當你啟動Redis的時候,Redis做了什么

文章目錄啟動過程初始化server結構體main函數會調用initServer函數初始化服務器狀態載入持久化文件&#xff0c;還原數據庫開始監聽事件流程圖啟動過程 初始化server結構體從配置文件夾在加載參數初始化服務器載入持久化文件開始監聽事件 初始化server結構體 服務器的運行ID…

linux中錯誤總結歸納

1.使用gcc編譯C文件&#xff0c;C文件在for循環語句中出現變量定義 編譯器提示錯誤&#xff1a;“for”loop initial declarations are only allowed in C99 mode. note:use option -stdc99or-stdgnu99 to compile; 原因&#xff1a;gcc的標準是基于c89的&#xff0c;c89不能在…

redis源碼剖析(十一)—— Redis字符串相關函數實現

文章目錄初始化字符串字符串基本操作字符串拼接操作other獲取指定范圍里的字符串將字符串中的所有字符均轉為小寫的形式將字符串中所有字符均轉為大寫的形式字符串比較other#define SDS_ABORT_ON_OOM#include "sds.h" #include <stdio.h> #include <stdlib.…

makefile內容小結

makefile中每個功能主要分為三部分&#xff1a;目標&#xff0c;依賴條件和命令語句 1.支持對比更新的Makefile寫法&#xff08;只會編譯文件時.o文件和.c文件時間不一致的文件&#xff09; 2.使用makefile自動變量和自定義變量的makefile寫法 其中&#xff1a;這三個符號為ma…

事務隔離級別動圖演示

事務的基本要素&#xff08;ACID&#xff09; 原子性&#xff08;Atomicity&#xff09; 事務開始后所有操作&#xff0c;要么全部做完&#xff0c;要么全部不做&#xff0c;不可能停滯在中間環節。事務執行過程中出錯&#xff0c;會回滾到事務開始前的狀態&#xff0c;所有的…

C/C++的優點和缺點

1.C/C語言的優點 C語言是面向過程的語言&#xff0c;常用來編寫操作系統。C語言是從C語言發展過來的&#xff0c;是一門面向對象的語言&#xff0c;它繼承了C語言的優勢&#xff0c;同時也添加了三個主要的內容&#xff1a;Oriented-Object class,Template,STL. 1)C/C可以潛入…

C/C++命令行參數那點事

int main(int argc, char *argv[ ]); 1.命令行參數&#xff1a;在命令行中給定的參數&#xff1b; 2.命令行參數在對函數main的調用時&#xff0c;主要有兩個參數送到main,一個是argc(argument count),命令行參數的個數&#xff0c;另外一個是argv,命令行參數的數組,命令行參…

mysql row_id為什么是6字節?為什么是8字節

mysql row_id是幾個字節&#xff1f; row_id InnoDB表中在沒有默認主鍵的情況下會生成一個6字節空間的自動增長主鍵 row_id是整型還是字符型&#xff1f; 源代碼中 row_id 是 ib_uint64_t 這是 8字節 uint64_t 是整形 為什么是6個字節&#xff1f; P.S. Base64編碼說明 B…

linux中的man文檔結構

使用命令 man chapter章節號查找的內容

偽隨機數和真隨機數

偽隨機數小項目 猜數字游戲 //C語言 猜數字游戲 https://blog.csdn.net/csdn_kou/article/details/79785709 C語言之隨機數生成超詳解 https://blog.csdn.net/csdn_kou/article/details/79788815 在上面的文章中&#xff0c;使用固定函數就一直是生成固定的隨機結果&#…

linux中的IO函數

1)open函數&#xff1a;以特定的方式打開一個文件&#xff1b; 頭文件&#xff1a;sys/type.h sys/stat.h fcntl.h 返回值&#xff1a;錯誤則返回-1&#xff0c;正確則返回文件描述符&#xff08;int類型&#xff0c;范圍為3~1023,文件的標號&#xff09; 函數原型&#xff…

ps -ef和ps aux

ps -ef和ps aux ps -ef unix風格 -e 列出所有進程 -f 完整格式 UID PID PPID C STIME TTY TIME CMD root 1 0 0 8月27 ? 00:25:08 /usr/lib/systemd/systemd --switched-root --system --deserialize 22 root 2 0 0 8月…

Linux中screen的用法

screen 查看當前有多少窗口 [rootpython ~]# screen -ls There are screens on:20706.khz (Attached)20679.khz (Attached)20453.khz (Attached)20143.khz (Detached)16993.pts-2.python (Attached) 5 Sockets in /var/run/screen/S-root.新建一…

linux文件操作相關函數

&#xff08;1&#xff09;stat函數&#xff1a;顯示文件的相關信息&#xff08;類似于 ls -l的感覺&#xff09; 頭文件及函數原型&#xff1a; 函數參數:path:文件的路徑&#xff0c;buf是指待寫入的文件信息&#xff0c;fd:表示文件描述符&#xff1b; stat,fstat,lstat三者…

linux查看硬盤是不是ssd固態硬盤

linux查看硬盤是不是ssd固態硬盤 sdb是ssd、sr0是SATA [root 01 ~]# cat /sys/block/sdb/queue/rotational 0 [root 01 ~]# cat /sys/block/sr0/queue/rotational 1

linux目錄操作函數

&#xff08;1&#xff09;chdir函數&#xff1a;修改當前進程的路徑 函數頭文件及原型&#xff1a; 參數&#xff1a;要修改的文件路徑或文件描述符&#xff08;一般是當前空閑最小的&#xff09; 返回值&#xff1a;成功&#xff08;0&#xff09;&#xff0c;失敗&#xff0…

linux中的dup和fcntl的用法

&#xff08;1&#xff09;dup函數&#xff1a;文件描述符的拷貝 函數頭文件及函數原型&#xff1a; 參數&#xff1a;原來的文件描述符&#xff0c;新的文件描述符&#xff0c;標志位&#xff1b; 返回值&#xff1a;成功&#xff08;返回新的文件描述符&#xff09;失敗&…

^M

為什么打開文件有^M 計算機還沒有出現之前&#xff0c;有一種叫做電傳打字機&#xff08;Teletype Model 33&#xff09;的玩意&#xff0c;每秒鐘可以打10個字符。但是它有一個問題&#xff0c;就是打完一行換行的時候&#xff0c;要用去0.2秒&#xff0c;正好可以打兩個字符…

使用dup2實現重定向到屏幕終端遇到問題

參考博客&#xff1a;https://blog.csdn.net/qq_26093511/article/details/53255970 參考博客&#xff1a;https://blog.csdn.net/db199410/article/details/52335450#commentBox 1.要解決的問題 通過復制文件描述符來實現文件重定向問題。 2.實現代碼 2.代碼輸出 按照原來的…