首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

多進程訪問 INI 配置文件衝突解決:文件鎖 + fstat 原子操作模式

     編輯:關於C語言

問題根因

進程 A 讀取文件大小 → 進程 B 寫入文件(大小變化) → 進程 A 按舊大小讀取 → 數據截斷/混亂 → 寫回破壞文件。

錯誤模式

stat(filename, &sb);      // 競態窗口打開
read(fd, buf, sb.st_size);

正確模式:文件鎖 + fstat 原子性

int fd = open(filename, O_RDWR);
flock(fd, LOCK_SH);       // 或 fcntl(F_SETLK, F_RDLCK)
fstat(fd, &sb);           // 基於已鎖定的 fd 獲取大小,原子
read(fd, buf, sb.st_size);
flock(fd, LOCK_UN);

兩種文件鎖對比

特性BSD flockPOSIX fcntl
粒度整個文件字節範圍
繼承fork 繼承不繼承
網絡文件系NFS 支持差NFS 支持較好
APIflock(fd, op)fcntl(fd, F_SETLK, &flk)

INI 解析器健壯性增強

  • 讀取失敗時輸出參數置空/非法值,防止髒數據滲透
  • 寫入採用「寫臨時文件 + rename 原子替換」模式
  • 文件格式版本號,兼容舊版本解析

完整讀寫框架

/* 讀 */
int read_ini(const char *file, IniData *out) {
    int fd = open(file, O_RDONLY);
    if (fd < 0) return -1;
    if (flock(fd, LOCK_SH)) { close(fd); return -2; }
    struct stat st; fstat(fd, &st);
    char *buf = malloc(st.st_size + 1);
    read(fd, buf, st.st_size); buf[st.st_size] = 0;
    flock(fd, LOCK_UN); close(fd);
    return parse_ini(buf, out);
}

/* 寫 */
int write_ini(const char *file, const IniData *in) {
    char tmp[PATH_MAX]; snprintf(tmp, sizeof(tmp), "%s.tmp.%d", file, getpid());
    int fd = open(tmp, O_WRONLY|O_CREAT|O_TRUNC, 0644);
    if (fd < 0) return -1;
    if (flock(fd, LOCK_EX)) { close(fd); unlink(tmp); return -2; }
    char *buf = serialize_ini(in);
    write(fd, buf, strlen(buf));
    flock(fd, LOCK_UN); close(fd);
    rename(tmp, file);  // 原子替換
    return 0;
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved