Linux進程通信之System V 共享內(nèi)存詳解
System V 共享內(nèi)存(Shared Memory)
System V 共享內(nèi)存是內(nèi)核在物理內(nèi)存中劃出的一塊連續(xù)內(nèi)存區(qū)域,允許多個進程將該區(qū)域映射到自身的虛擬地址空間中。進程對這塊內(nèi)存的讀寫操作完全等同于本地內(nèi)存(無需系統(tǒng)調(diào)用 / 數(shù)據(jù)拷貝),是所有 IPC 機制中速度最快的(“零拷貝” 特性)。其核心價值是解決 “大量數(shù)據(jù)在進程間傳輸” 的性能問題,但本身無內(nèi)置同步機制,需配合信號量等工具實現(xiàn)互斥 / 同步。

核心功能
- 最快的 IPC 機制:內(nèi)核開辟一塊連續(xù)的內(nèi)存區(qū)域,映射到多個進程的虛擬地址空間(共享區(qū)),進程直接讀寫該內(nèi)存(無需內(nèi)核中轉(zhuǎn));
- 無數(shù)據(jù)拷貝(其他 IPC 需多次拷貝:用戶態(tài)→內(nèi)核態(tài)→用戶態(tài)),性能極致;
- 無同步機制:需配合信號量 / 互斥鎖防止 “讀寫沖突”(如進程 A 寫時進程 B 讀)。
核心特征
| 特性 | 說明 |
|---|---|
| 零拷貝 | 數(shù)據(jù)直接在進程虛擬地址空間讀寫,無read()/write()的拷貝開銷(相比管道 / 消息隊列的 2 次拷貝) |
| 內(nèi)核持久化 | 內(nèi)存段存在于內(nèi)核中,進程退出后不消失,需顯式刪除 |
| 無內(nèi)置同步 | 共享內(nèi)存無鎖 / 阻塞機制,需配合信號量 / 互斥鎖避免 “競態(tài)條件” |
| 地址獨立 | 不同進程映射到的虛擬地址不同,但指向同一塊物理內(nèi)存 |
| 大小對齊 | 內(nèi)存大小按系統(tǒng)頁大小(通常 4KB)對齊,不足一頁按一頁分配 |
與其他 IPC 機制的性能對比
| IPC 機制 | 數(shù)據(jù)拷貝次數(shù) | 核心開銷 | 適用場景 | 性能排序 |
|---|---|---|---|---|
| System V 共享內(nèi)存 | 0 次 | 僅內(nèi)存映射 / 同步開銷 | 大量數(shù)據(jù)、高性能需求的通信 | 1 |
| System V 消息隊列 | 2 次(用戶→內(nèi)核→用戶) | 系統(tǒng)調(diào)用 + 拷貝開銷 | 結(jié)構(gòu)化、帶類型的小數(shù)據(jù)通信 | 2 |
| 命名管道(FIFO) | 2 次 | 系統(tǒng)調(diào)用 + 拷貝開銷 | 簡單流式數(shù)據(jù)通信 | 3 |
| 匿名管道 | 2 次 | 系統(tǒng)調(diào)用 + 拷貝開銷 | 親緣進程臨時通信 | 3 |
問題:同步依賴
共享內(nèi)存的 “零拷貝” 優(yōu)勢也帶來了風(fēng)險:多個進程可同時讀寫同一塊內(nèi)存,若沒有同步機制,會出現(xiàn) “一個進程寫了一半,另一個進程就讀取” 的 “競態(tài)條件”(數(shù)據(jù)錯亂)。因此,共享內(nèi)存必須配合信號量(System V/POSIX)或互斥鎖使用,實現(xiàn) “臨界區(qū)獨占訪問”。
使用流程
- 用
ftok()生成唯一鍵值; - 創(chuàng)建內(nèi)存段:進程調(diào)用
shmget(),內(nèi)核在物理內(nèi)存中分配一塊連續(xù)區(qū)域,初始化shmid_ds; - 映射到進程空間:進程調(diào)用
shmat(),內(nèi)核修改該進程的頁表,將虛擬地址映射到共享物理內(nèi)存; - 進程讀寫:進程直接通過虛擬地址讀寫物理內(nèi)存,數(shù)據(jù)對所有映射的進程立即可見;
- 解除映射:進程調(diào)用
shmdt(),內(nèi)核修改頁表,解除虛擬地址與物理內(nèi)存的關(guān)聯(lián); - 刪除內(nèi)存段:最后一個進程解除映射后,調(diào)用
shmctl(IPC_RMID),內(nèi)核釋放物理內(nèi)存。
關(guān)鍵:多個進程的虛擬地址不同,但頁表指向同一塊物理內(nèi)存,因此修改對所有進程可見。
函數(shù)解釋
所有操作需包含以下頭文件:
#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h>
1. ftok ():生成 IPC 唯一鍵值
將「文件路徑」和「項目 ID」轉(zhuǎn)換為key_t類型的整數(shù)鍵值,用于標(biāo)識 System V IPC 對象(共享內(nèi)存、消息隊列、信號量)。不同進程使用相同的路徑和項目 ID,可生成相同的鍵值,從而訪問同一個 IPC 對象。
key_t ftok(const char *pathname, int proj_id);
| 參數(shù) | 說明 |
|---|---|
| pathname | 必須是存在且可訪問的文件路徑(如/tmp/test),文件僅作為標(biāo)識,無需讀寫。 |
| proj_id | 項目標(biāo)識(低 8 位有效,通常取 1-255),僅用于區(qū)分同一文件下的不同 IPC 對象。 |
返回值
- 成功:返回唯一的
key_t類型整數(shù)(通常是 int 別名); - 失?。悍祷?code>-1,并設(shè)置
errno(如ENOENT路徑不存在、EACCES權(quán)限不足)。
注意事項
- 若文件被刪除后重建,即使路徑和 ID 相同,生成的鍵值也會變化;
- 若無需跨進程共享,可直接用
IPC_PRIVATE替代 ftok 生成的鍵值(僅當(dāng)前進程 / 子進程可用)。
2. shmget ():創(chuàng)建 / 獲取共享內(nèi)存段
在內(nèi)核中創(chuàng)建或獲取共享內(nèi)存段,返回唯一的shmid(共享內(nèi)存標(biāo)識符),內(nèi)核會為每個共享內(nèi)存段維護一個shmid_ds結(jié)構(gòu)體(存儲大小、權(quán)限、映射數(shù)等信息)。
int shmget(key_t key, size_t size, int shmflg);
| 參數(shù) | 說明 |
|---|---|
| key | ftok 生成的鍵值,或IPC_PRIVATE(創(chuàng)建私有共享內(nèi)存)。 |
| size | 共享內(nèi)存大?。ㄗ止?jié)):- 創(chuàng)建時:必須指定(按系統(tǒng)頁大小 4K 對齊,不足則向上取整);- 獲取時:設(shè)為 0。 |
| shmflg | 標(biāo)志位(按位或組合):- IPC_CREAT:不存在則創(chuàng)建,存在則獲取;- IPC_EXCL:與IPC_CREAT聯(lián)用,若已存在則失?。ù_保創(chuàng)建新段);- 權(quán)限位:如0664(同文件權(quán)限,八進制)。 |
返回值
- 成功:返回非負整數(shù)
shmid(共享內(nèi)存標(biāo)識符); - 失?。悍祷?code>-1,設(shè)置
errno(如EEXIST已存在、ENOMEM內(nèi)存不足、EINVALsize 無效)。
注意事項
- 共享內(nèi)存創(chuàng)建后,即使創(chuàng)建進程退出,也會一直存在于內(nèi)核,直到被
shmctl刪除或系統(tǒng)重啟; - 權(quán)限位需與后續(xù)
shmat的讀寫權(quán)限匹配(如SHM_RDONLY需 shmget 設(shè)置讀權(quán)限)。
3. shmat ():映射共享內(nèi)存到進程地址空間
將內(nèi)核中的共享內(nèi)存段附加(映射) 到進程的虛擬地址空間,返回映射后的地址,進程可直接讀寫該地址(等同于操作普通內(nèi)存)。
void *shmat(int shmid, const void *shmaddr, int shmflg);
| 參數(shù) | 說明 |
|---|---|
| shmid | shmget 返回的共享內(nèi)存標(biāo)識符。 |
| shmaddr | 指定映射到進程的虛擬地址:- 設(shè)NULL(推薦):由系統(tǒng)自動分配;- 非 NULL:需對齊頁大小,通常不推薦。 |
| shmflg | 映射標(biāo)志:- 0:默認,讀寫權(quán)限;- SHM_RDONLY:只讀權(quán)限(需 shmget 設(shè)置讀權(quán)限)。 |
返回值
- 成功:返回映射后的虛擬地址(
void*); - 失?。悍祷?code>(void*)-1,設(shè)置
errno(如EINVALshmid 無效、EACCES權(quán)限不足)。
注意事項
- 多個進程可映射同一個共享內(nèi)存段,讀寫操作直接同步;
- 映射后進程退出,共享內(nèi)存不會自動刪除,僅解除映射。
4. shmdt ():解除共享內(nèi)存映射
將共享內(nèi)存段與進程的虛擬地址空間分離(解除映射),僅斷開關(guān)聯(lián),不刪除內(nèi)核中的共享內(nèi)存。
int shmdt(const void *shmaddr);
| 參數(shù) | 說明 |
|---|---|
| shmaddr | shmat 返回的映射地址。 |
返回值
- 成功:返回
0; - 失?。悍祷?code>-1,設(shè)置
errno(如EINVAL地址不是映射地址)。
注意事項
- 解除映射后,進程不可再訪問該地址,否則觸發(fā)段錯誤;
- 若所有進程都解除映射,共享內(nèi)存仍存在于內(nèi)核,需
shmctl主動刪除。
5. shmctl ():控制共享內(nèi)存段(核心:刪除)
System V 共享內(nèi)存的控制接口,支持獲取狀態(tài)、設(shè)置屬性、刪除共享內(nèi)存(最常用IPC_RMID命令)。
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
| 參數(shù) | 說明 |
|---|---|
| shmid | shmget 返回的共享內(nèi)存標(biāo)識符。 |
| cmd | 操作命令(核心):- IPC_STAT:讀取共享內(nèi)存狀態(tài),存入buf;- IPC_SET:修改共享內(nèi)存屬性(從buf讀取);- IPC_RMID:刪除共享內(nèi)存段(內(nèi)核釋放資源)。 |
| buf | struct shmid_ds結(jié)構(gòu)體指針:- IPC_STAT/IPC_SET:存儲 / 讀取狀態(tài);- IPC_RMID:設(shè)NULL即可。 |
核心結(jié)構(gòu)體(簡化版)
struct shmid_ds {
struct ipc_perm shm_perm; // 權(quán)限結(jié)構(gòu)體(含所有者、權(quán)限位等)
size_t shm_segsz; // 共享內(nèi)存大?。ㄗ止?jié))
pid_t shm_lpid; // 最后操作的進程ID
pid_t shm_cpid; // 創(chuàng)建進程ID
shmatt_t shm_nattch; // 當(dāng)前映射的進程數(shù)
time_t shm_atime; // 最后映射時間
time_t shm_dtime; // 最后解除映射時間
};
返回值
- 成功:返回
0(IPC_STAT/IPC_SET/IPC_RMID); - 失?。悍祷?code>-1,設(shè)置
errno(如EINVALshmid 無效、EPERM權(quán)限不足)。
注意事項
- 執(zhí)行
IPC_RMID后,內(nèi)核標(biāo)記共享內(nèi)存為「待刪除」:- 若仍有進程映射,新進程無法再映射該段;- 當(dāng)所有進程解除映射后,內(nèi)核才真正釋放資源; - 普通用戶僅能刪除自己創(chuàng)建的共享內(nèi)存,root 可刪除所有。
完整示例(創(chuàng)建→寫入→讀取→刪除)
1. 寫進程(shm_write.c)
#include <stdio.h> // 提供printf、perror等輸入輸出函數(shù)
#include <stdlib.h> // 提供exit()退出函數(shù)(進程出錯時終止)
#include <string.h> // 提供strncpy字符串拷貝函數(shù)
#include <sys/ipc.h> // 提供ftok()函數(shù)(生成IPC鍵值)
#include <sys/shm.h> // 提供shmget/shmat/shmdt/shmctl等共享內(nèi)存核心函數(shù)
#include <unistd.h> // 提供getchar()(等待用戶輸入)、系統(tǒng)調(diào)用基礎(chǔ)功能
// 2. 宏定義:把固定值抽出來,方便修改和理解
#define PATHNAME "/tmp/shm_test" // ftok需要的文件路徑(必須存在!小白要先touch這個文件)
#define PROJ_ID 100 // 項目ID(僅低8位有效,隨便設(shè)1-255之間的數(shù)即可)
#define SHM_SIZE 4096 // 共享內(nèi)存大小(字節(jié)),4096是系統(tǒng)頁大小(對齊要求,不能隨便設(shè)?。?
int main() {
// -------------------------- 步驟1:生成唯一的IPC鍵值 --------------------------
// key_t是專門存IPC鍵值的類型(本質(zhì)是整數(shù))
// ftok作用:把"文件路徑+項目ID"轉(zhuǎn)換成唯一整數(shù),讓讀寫進程能找到同一個共享內(nèi)存
key_t key = ftok(PATHNAME, PROJ_ID);
// 檢查ftok是否失敗(返回-1就是失?。?
if (key == -1) {
// perror:自動打印"xxx failed: 具體錯誤原因"(比如文件不存在會提示No such file)
perror("ftok failed");
exit(1); // 1表示異常退出(0是正常退出),終止進程
}
// -------------------------- 步驟2:創(chuàng)建共享內(nèi)存段 --------------------------
// shmget作用:向內(nèi)核申請一塊共享內(nèi)存,返回"共享內(nèi)存ID(shmid)"(類似文件句柄)
// 參數(shù)1:ftok生成的鍵值(標(biāo)識共享內(nèi)存)
// 參數(shù)2:共享內(nèi)存大小(必須是系統(tǒng)頁大小的整數(shù)倍,4096是最常用的)
// 參數(shù)3:標(biāo)志位組合(IPC_CREAT=創(chuàng)建新的 | IPC_EXCL=如果已存在則報錯 | 0664=權(quán)限,和文件權(quán)限一樣)
int shmid = shmget(key, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0664);
// 檢查shmget是否失敗(比如內(nèi)存不足、鍵值已存在)
if (shmid == -1) {
perror("shmget failed");
exit(1);
}
// 打印shmid,方便調(diào)試(比如用ipcs -m命令查看時能對應(yīng)上)
printf("共享內(nèi)存ID(shmid):%d\n", shmid);
// -------------------------- 步驟3:把共享內(nèi)存映射到進程地址空間 --------------------------
// shmat作用:把內(nèi)核里的共享內(nèi)存,"掛到"當(dāng)前進程的內(nèi)存地址上,進程才能直接讀寫
// 參數(shù)1:shmget返回的共享內(nèi)存ID
// 參數(shù)2:指定映射的地址(設(shè)NULL讓系統(tǒng)自動分配,小白千萬別改)
// 參數(shù)3:映射權(quán)限(0=讀寫,SHM_RDONLY=只讀)
// 返回值:映射后的內(nèi)存地址(進程直接操作這個地址就等于操作共享內(nèi)存)
char *shm_addr = (char *)shmat(shmid, NULL, 0);
// 檢查映射是否失?。ǚ祷?void*)-1就是失敗,注意強制類型轉(zhuǎn)換)
if (shm_addr == (void *)-1) {
perror("shmat failed");
exit(1);
}
// -------------------------- 步驟4:向共享內(nèi)存寫入數(shù)據(jù) --------------------------
// 要寫入的字符串(小白注意:C語言字符串末尾有個隱藏的'\0',表示結(jié)束)
const char *msg = "Hello, Shared Memory!";
// strncpy:把msg拷貝到共享內(nèi)存地址shm_addr
// 第三個參數(shù):strlen(msg)+1 是為了把末尾的'\0'也拷貝過去(否則讀的時候會亂碼)
strncpy(shm_addr, msg, strlen(msg) + 1);
// 打印寫入的內(nèi)容,確認寫成功
printf("已向共享內(nèi)存寫入:%s\n", shm_addr);
// -------------------------- 等待讀進程讀取數(shù)據(jù) --------------------------
// 暫停進程,等用戶按回車再繼續(xù)(給讀進程留時間讀取,否則寫進程直接刪了共享內(nèi)存,讀進程就讀不到了)
printf("請按回車鍵繼續(xù)(此時可以啟動讀進程讀取數(shù)據(jù))...\n");
getchar(); // 阻塞等待用戶輸入回車
// -------------------------- 步驟5:解除共享內(nèi)存映射 --------------------------
// shmdt作用:把共享內(nèi)存和當(dāng)前進程"解綁"(進程不再能訪問這個地址,但共享內(nèi)存還在內(nèi)核里)
// 參數(shù):shmat返回的映射地址
if (shmdt(shm_addr) == -1) {
perror("shmdt failed");
exit(1);
}
// -------------------------- 步驟6:刪除共享內(nèi)存(釋放內(nèi)核資源) --------------------------
// shmctl作用:控制共享內(nèi)存(這里用IPC_RMID命令刪除)
// 參數(shù)1:共享內(nèi)存ID
// 參數(shù)2:操作命令(IPC_RMID=刪除共享內(nèi)存)
// 參數(shù)3:共享內(nèi)存的狀態(tài)結(jié)構(gòu)體(刪除時設(shè)NULL即可)
if (shmctl(shmid, IPC_RMID, NULL) == -1) {
perror("shmctl failed");
exit(1);
}
// 正常退出進程(0表示無錯誤)
return 0;
}2. 讀進程(shm_read.c)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#define PATHNAME "/tmp/shm_test"
#define PROJ_ID 100
#define SHM_SIZE 4096
int main() {
// 1. 生成相同鍵值
key_t key = ftok(PATHNAME, PROJ_ID);
if (key == -1) {
perror("ftok failed");
exit(1);
}
// 2. 獲取已存在的共享內(nèi)存(size設(shè)0,僅獲取)
int shmid = shmget(key, 0, 0);
if (shmid == -1) {
perror("shmget failed");
exit(1);
}
printf("shmid: %d\n", shmid);
// 3. 映射(只讀權(quán)限)
char *shm_addr = (char *)shmat(shmid, NULL, SHM_RDONLY);
if (shm_addr == (void *)-1) {
perror("shmat failed");
exit(1);
}
// 4. 讀取數(shù)據(jù)
printf("Read from shm: %s\n", shm_addr);
// 5. 解除映射
if (shmdt(shm_addr) == -1) {
perror("shmdt failed");
exit(1);
}
return 0;
}
編譯與運行
# 先創(chuàng)建標(biāo)識文件 touch /tmp/shm_test # 編譯 gcc shm_write.c -o shm_write gcc shm_read.c -o shm_read # 先運行寫進程 ./shm_write # 再新開終端運行讀進程 ./shm_read
常用輔助命令
| 命令 | 說明 |
|---|---|
| ipcs -m | 查看所有共享內(nèi)存段 |
| ipcrm -m <shmid> | 命令行刪除指定共享內(nèi)存 |
| cat /proc/sys/kernel/shmmax | 查看共享內(nèi)存最大限制 |
內(nèi)核為每個共享內(nèi)存段維護關(guān)鍵元數(shù)據(jù)結(jié)構(gòu) struct shmid_ds(類似文件的inode):
struct shmid_ds {
struct ipc_perm shm_perm; // 權(quán)限信息(UID/GID、訪問權(quán)限)
size_t shm_segsz; // 共享內(nèi)存段大?。ㄗ止?jié),按頁對齊)
pid_t shm_lpid; // 最后操作的進程ID
pid_t shm_cpid; // 創(chuàng)建進程ID
shmatt_t shm_nattch;// 當(dāng)前映射該段的進程數(shù)
time_t shm_atime; // 最后映射時間
time_t shm_dtime; // 最后解除映射時間
time_t shm_ctime; // 最后修改時間
};關(guān)鍵注意事項
1 同步是必選項
共享內(nèi)存無任何內(nèi)置同步機制,多個進程同時讀寫會導(dǎo)致數(shù)據(jù)錯亂(如寫進程寫了一半,讀進程就讀?。?。必須配合:
- System V/POSIX 信號量(互斥 / 同步);
- 互斥鎖(pthread_mutex_t);
- 自定義標(biāo)志(如共享內(nèi)存中加 “是否寫入完成” 的標(biāo)記)。
2 內(nèi)存大小與對齊
shmget()的size參數(shù)會按系統(tǒng)頁大小(通常 4KB)對齊,例如申請 100 字節(jié),內(nèi)核實際分配 4096 字節(jié);- 建議按頁大小申請(如 4096、8192),避免內(nèi)存浪費。
3 資源泄漏問題
- 共享內(nèi)存段是內(nèi)核資源,進程退出(即使異常)不會自動刪除,僅解除映射(
shmdt); - 未調(diào)用
shmctl(IPC_RMID)會導(dǎo)致內(nèi)存段永久占用內(nèi)核資源,直到系統(tǒng)重啟; - 解決:確保至少一個進程執(zhí)行
IPC_RMID,或通過ipcrm -m <shmid>手動刪除。
4 權(quán)限與訪問控制
shmget()的shmflg需設(shè)置正確權(quán)限(如0666),否則其他進程無法映射 / 讀寫;- 若進程 UID/GID 不匹配,會返回
EACCES錯誤,需檢查權(quán)限設(shè)置。
5 進程異常退出處理
- 進程異常退出時,內(nèi)核會自動解除其共享內(nèi)存映射(
shmdt),但內(nèi)存段仍存在; - 信號量需設(shè)置
SEM_UNDO,避免進程異常退出導(dǎo)致死鎖。
System V 共享內(nèi)存 vs POSIX 共享內(nèi)存
| 特性 | System V 共享內(nèi)存 | POSIX 共享內(nèi)存(mmap+shm_open) |
|---|---|---|
| 標(biāo)識方式 | 鍵值(key)+ 標(biāo)識符(shmid) | 文件系統(tǒng)路徑(/dev/shm/xxx) |
| 持久化 | 內(nèi)核持久化(需顯式刪除) | 文件系統(tǒng)持久化(需 unlink) |
| 接口復(fù)雜度 | 較低(5 個核心函數(shù)) | 較高(mmap/shm_open/ftruncate) |
| 跨進程可見性 | 需 ftok 生成 key | 路徑可見,更易管理 |
| 大小調(diào)整 | 創(chuàng)建時固定 | 可通過 ftruncate 動態(tài)調(diào)整 |
| 現(xiàn)代支持 | 傳統(tǒng)接口,維護中 | 現(xiàn)代接口,推薦使用 |
總結(jié)
System V 共享內(nèi)存是性能最高的 IPC 機制,核心是 “內(nèi)核物理內(nèi)存映射到進程虛擬地址空間”,實現(xiàn)零拷貝數(shù)據(jù)共享;
核心操作流程:ftok()生成鍵值 → shmget()創(chuàng)建 / 獲取段 → shmat()映射到進程空間 → 讀寫數(shù)據(jù) → shmdt()解除映射 → shmctl(IPC_RMID)刪除段;
關(guān)鍵要點:
- 必須配合信號量 / 互斥鎖實現(xiàn)同步,避免競態(tài)條件;
- 內(nèi)存大小按頁對齊,按需申請避免浪費;
- 用完必須調(diào)用
shmctl(IPC_RMID),防止內(nèi)核資源泄漏;
現(xiàn)代開發(fā)中,POSIX 共享內(nèi)存(shm_open+mmap)更易管理,但 System V 共享內(nèi)存仍是傳統(tǒng)高性能 IPC 的核心選擇。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Linux云服務(wù)器安裝JDK和Tomcat的詳細步驟(推薦)
這篇文章主要介紹了Linux云服務(wù)器安裝JDK和Tomcat的詳細步驟,本文分步驟給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-12-12
linux使用tcpdump命令監(jiān)視指定網(wǎng)絡(luò)數(shù)據(jù)包的方法
linux使用tcpdump命令監(jiān)視指定網(wǎng)絡(luò)數(shù)據(jù)包的方法,大家參考使用吧2013-12-12
詳解為新版Apache服務(wù)器開啟HTTP/2支持的方法
這篇文章主要介紹了在Apache服務(wù)器中開啟HTTP/2的方法,HTTP/2被稱為未來的新HTTP協(xié)議,需要的朋友可以參考下2015-12-12
Linux內(nèi)核設(shè)備驅(qū)動之虛擬文件系統(tǒng)筆記整理
今天小編就為大家分享一篇關(guān)于Linux內(nèi)核設(shè)備驅(qū)動之虛擬文件系統(tǒng)筆記整理,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12
Linux下SVN服務(wù)器同時支持Apache的http和svnserve獨立服務(wù)器兩種模式且使用相同的訪問權(quán)限賬號
這篇文章主要介紹了Linux下SVN服務(wù)器同時支持Apache的http和svnserve獨立服務(wù)器兩種模式且使用相同的訪問權(quán)限賬號,需要的朋友可以參考下2015-07-07

