[ 永遠的UNIX::UNIX技術資料的寶庫 ]   GB | BIG5

首頁 > 編程技術 > 其它 > 正文
UNIX系統的文件信號燈機制
本文出自: 作者: (2001-07-06 19:00:01)

--- 作 為 一 個 多 用 戶、 多 任 務 的 操 作 系 統,UNIX 允 許 某 個 程 序 同 時 運 行 多 個 進 程。 但 有 時 又 由 系 統 資 源 等 因 素 的 制 約, 要 求 一 次 只 能 有 一 個 進 程 在 運 行。 例 如 在Digital UNIX 下 運 行 第 二 個Netscape 進 程 時, 系 統 報 告 如 下 錯 誤 信 息:

---- Netscape has detected a /.netscape/lock file.
---- This may indicate that another user is running Netscape using your /.netscape files.

---- 實 際 上, 第 一 個Netscape 進 程 在 運 行 時, 加 了 一 把 鎖, 禁 止 其 他Netscape 進 程 啟 動。 當 它 結 束 時, 把 鎖 打 開, 其 他 進 程 才 能 進 入。 這 就 是UNIX 的 信 號 燈 機 制。

---- 而Netscape 是 用 文 件 作 為 信 號 燈 的。 在 運 行 前, 先 檢 查 文 件/.netscape/lock 是 否 存 在: 若 存 在, 表 明 鎖 已 掛 上, 新 進 程 不 能 運 行, 只 好 等 待; 若 沒 有, 說 明 鎖 已 打 開, 可 以 運 行 了。

---- 在 掌 握 了 文 件 信 號 燈 的 機 理 , 可 以 自 行 設 計 一 套 萬 能 加 鎖 解 鎖 程 序, 為 每 個 程 序 配 上 各 自 的 鎖 和 鑰 匙。 並 且 使 用 零 字 節 長 度 的 文 件 當 鎖, 減 少 系 統 開 銷。

---- 我 們 用creat 和unlink 兩 個 系 統 調 用 實 現 加 解 鎖 和 檢 測 操 作。 一 個 進 程 運 行 之 前, 先 通 過unlink 檢 測 鎖 文 件 是 否 存 在 注1。unlink 系 統 調 用 從 一 個 目 錄 中 刪 去 一 個 文 件 鏈, 若 成 功 則 返 回0, 表 示 確 有 文 件 存 在; 若 失 敗, 表 明 文 件 不 存 在, 返 回-1。 如 果 還 沒 有 上 鎖, 就 要 用creat 系 統 調 用 創 建 鎖 文 件; 若 鎖 已 掛 上, 雖 然 進 程 並 未 運 行, 但 unlink 無 疑 會 刪 除 鎖 文 件, 所 以 也 要 用creat 來 恢 復。creat 系 統 調 用 創 建 一 個 新 文 件, 函 數 標 題 如 下:


int creat(path, perms) /* create file */
char *path; /* path name */
int perms; /* permission bits */

---- 其 中path 表 示 路 徑 加 文 件 名,perms 是10 位 的 文 件 權 限 描 述 字, 在 加 鎖 程 序 中 取0。 文 件 在 剛 創 建 時, 初 始 長 度 為 零 字 節, 用 它 來 做 鎖 文 件, 可 以 最 大 限 度 地 降 低 系 統 開 銷。

---- 鎖 文 件 規 定 為: 源 文 件 名+“.lok”。 這 樣 一 來, 就 真 正 做 到 了 一 個 程 序 配 一 把 鎖。

---- 下 面 就 列 出 加 鎖 和 解 鎖 的 程 序 清 單。 我 們 用 同 樣 的 程 序 完 成 這 兩 種 完 全 互 斥 的 操 作, 區 別 在 命 令 名 的 不 同。 在C 語 言 源 程 序 裡, 變 量argv[0] 表 示 命 令 名,“lockf” 是 上 鎖,“unlockf” 是 解 鎖。


程序LOCKF.C暨UNLOCKF.C的源代碼
#include < stdio.h >
#include < errno.h >
#include < fcntl.h >
#include < cdatyp.h >
void syserr(msg) /*打印系統調用錯誤信息並中止 */
char *msg;
{
extern int errno, sys_nerr;
extern char *sys_errlist[];

fprintf(stderr, "ERROR: %s (%d", msg, errno);
if (errno >0 && errno< sys_nerr)
fprintf(stderr, "; %s)\n", sys_errlist[errno]);
else
fprintf(stderr, ")\n");
exit(1);
}
short nlock(name) /*上鎖過程 */
char *name;
{ char *path, *lockpath();
int fd, tries;
extern int errno;
short unlink_result;

path=lockpath(name); /*制鎖 */
unlink_result=unlink(path); /*判斷是否已經上鎖 */
fd=creat(path, 0); /*上鎖 */
if (fd==-1 || close(fd)==-1)
syserr("nlock");
if (unlink_result==-1)
return 0xff;
return (0);
}
void nunlock(name) /*解鎖 */
char *name;
{ char *lockpath();
if (unlink(lockpath(name))==-1)
syserr("nunlock");
}
static char *lockpath(name) /*制鎖的過程 */
char *name;
{ static char path[20];
char *strcat();

strcpy(path, name);
return(strcat(path, ".lok"));
}
int main(argc, argv)
int argc;
char *argv[];
{ if (argc!=2)
{ printf("Usage: %s filename\n\r", argv[0]);
return(1);
}
if (strcmp(argv[0], "lockf")==0)
if (!nlock(argv[1]))
{ printf("You can not add the same lock twice!\r\n");
return(2);
}
if (strcmp(argv[0], "unlockf")==0)
nunlock(argv[1]);
return(0);
}
本程序的用法是:
lockf 源文件名

unlockf 源文件名

---- 要 真 正 實 現 信 號 燈 機 制, 我 們 還 必 須 準 備 一 個 簡 單 的script 文 件signal: if lockf $1 $1 注2 unlockf else echo “Error: Another $1 is running.” fi

---- 這 樣 我 們 在 運 行 文 本 編 輯 器dtpad 時, 輸 入 下 列 命 令:

---- signal dtpad

---- 反 過 來, 對 前 面 提 到 的netscape 程 序, 也 可 以 通 過 編 寫 一 個script 文 件supernet 實 現 多 個 進 程 同 時 運 行:


netscape &
rm /.netscape/lock

---- 注1: 還 有 一 種 方 法, 只 適 用 普 通 用 戶: 在creat 創 建 一 個 新 文 件 時, 即 使 權 限 實 參(permission argument) 不 允 許 寫, 該 文 件 也 被 打 開 用 作 寫。 但creat 在 截 斷 一 個 現 存 文 件 時, 若 無 寫 權 限(write permission), 則 失 敗。 這 樣 就 可 以 只 通 過creat 系 統 調 用 實 現 文 件 信 號 燈 機 制。 但 這 種 做 法 有 一 個 很 明 顯 的 缺 點, 就 是 不 適 用 超 級 用 戶, 因 為 對 超 級 用 戶 沒 有 不 允 許 寫 的 東 西。

---- 注2: 這 不 適 帶& 符 號 的 台 進 程。

---- UNIX 系 統 的 文 件 信 號 燈 機 制

---- 作 為 一 個 多 用 戶、 多 任 務 的 操 作 系 統,UNIX 允 許 某 個 程 序 同 時 運 行 多 個 進 程。 但 有 時 又 由 系 統 資 源 等 因 素 的 制 約, 要 求 一 次 只 能 有 一 個 進 程 在 運 行。 例 如 在Digital UNIX 下 運 行 第 二 個Netscape 進 程 時, 系 統 報 告 如 下 錯 誤 信 息:

---- Netscape has detected a /.netscape/lock file.

---- This may indicate that another user is running Netscape using your /.netscape files.

---- 實 際 上, 第 一 個Netscape 進 程 在 運 行 時, 加 了 一 把 鎖, 禁 止 其 他Netscape 進 程 啟 動。 當 它 結 束 時, 把 鎖 打 開, 其 他 進 程 才 能 進 入。 這 就 是UNIX 的 信 號 燈 機 制。

---- 而Netscape 是 用 文 件 作 為 信 號 燈 的。 在 運 行 前, 先 檢 查 文 件/.netscape/lock 是 否 存 在: 若 存 在, 表 明 鎖 已 掛 上, 新 進 程 不 能 運 行, 只 好 等 待; 若 沒 有, 說 明 鎖 已 打 開, 可 以 運 行 了。

---- 在 掌 握 了 文 件 信 號 燈 的 機 理 , 可 以 自 行 設 計 一 套 萬 能 加 鎖 解 鎖 程 序, 為 每 個 程 序 配 上 各 自 的 鎖 和 鑰 匙。 並 且 使 用 零 字 節 長 度 的 文 件 當 鎖, 減 少 系 統 開 銷。

---- 我 們 用creat 和unlink 兩 個 系 統 調 用 實 現 加 解 鎖 和 檢 測 操 作。 一 個 進 程 運 行 之 前, 先 通 過unlink 檢 測 鎖 文 件 是 否 存 在 注1。unlink 系 統 調 用 從 一 個 目 錄 中 刪 去 一 個 文 件 鏈, 若 成 功 則 返 回0, 表 示 確 有 文 件 存 在; 若 失 敗, 表 明 文 件 不 存 在, 返 回-1。 如 果 還 沒 有 上 鎖, 就 要 用creat 系 統 調 用 創 建 鎖 文 件; 若 鎖 已 掛 上, 雖 然 進 程 並 未 運 行, 但 unlink 無 疑 會 刪 除 鎖 文 件, 所 以 也 要 用creat 來 恢 復。creat 系 統 調 用 創 建 一 個 新 文 件, 函 數 標 題 如 下:


int creat(path, perms) /* create file */
char *path; /* path name */
int perms; /* permission bits */

---- 其 中path 表 示 路 徑 加 文 件 名,perms 是10 位 的 文 件 權 限 描 述 字, 在 加 鎖 程 序 中 取0。 文 件 在 剛 創 建 時, 初 始 長 度 為 零 字 節, 用 它 來 做 鎖 文 件, 可 以 最 大 限 度 地 降 低 系 統 開 銷。

---- 鎖 文 件 規 定 為: 源 文 件 名+“.lok”。 這 樣 一 來, 就 真 正 做 到 了 一 個 程 序 配 一 把 鎖。

---- 下 面 就 列 出 加 鎖 和 解 鎖 的 程 序 清 單。 我 們 用 同 樣 的 程 序 完 成 這 兩 種 完 全 互 斥 的 操 作, 區 別 在 命 令 名 的 不 同。 在C 語 言 源 程 序 裡, 變 量argv[0] 表 示 命 令 名,“lockf” 是 上 鎖,“unlockf” 是 解 鎖。

---- 程 序LOCKF.C 暨UNLOCKF.C 的 源 代 碼


#include < stdio.h >
#include < errno.h >
#include < fcntl.h >
#include < cdatyp.h >
void syserr(msg) /*打印系統調用錯誤信息並中止 */
char *msg;
{
extern int errno, sys_nerr;
extern char *sys_errlist[];

fprintf(stderr, "ERROR: %s (%d", msg, errno);
if (errno >0 && errno< sys_nerr)
fprintf(stderr, "; %s)\n", sys_errlist[errno]);
else
fprintf(stderr, ")\n");
exit(1);
}
short nlock(name) /*上鎖過程 */
char *name;
{ char *path, *lockpath();
int fd, tries;
extern int errno;
short unlink_result;

path=lockpath(name); /*制鎖 */
unlink_result=unlink(path); /*判斷是否已經上鎖 */
fd=creat(path, 0); /*上鎖 */
if (fd==-1 || close(fd)==-1)
syserr("nlock");
if (unlink_result==-1)
return 0xff;
return (0);
}
void nunlock(name) /*解鎖 */
char *name;
{ char *lockpath();
if (unlink(lockpath(name))==-1)
syserr("nunlock");
}
static char *lockpath(name) /*制鎖的過程 */
char *name;
{ static char path[20];
char *strcat();

strcpy(path, name);
return(strcat(path, ".lok"));
}
int main(argc, argv)
int argc;
char *argv[];
{ if (argc!=2)
{ printf("Usage: %s filename\n\r", argv[0]);
return(1);
}
if (strcmp(argv[0], "lockf")==0)
if (!nlock(argv[1]))
{ printf("You can not add the same lock twice!\r\n");
return(2);
}
if (strcmp(argv[0], "unlockf")==0)
nunlock(argv[1]);
return(0);
}
本程序的用法是:
lockf 源文件名

unlockf 源文件名

---- 要 真 正 實 現 信 號 燈 機 制, 我 們 還 必 須 準 備 一 個 簡 單 的script 文 件signal:


if lockf $1
$1 注2
unlockf
else
echo “Error: Another $1 is running.”
fi

---- 這 樣 我 們 在 運 行 文 本 編 輯 器dtpad 時, 輸 入 下 列 命 令:

---- signal dtpad

---- 反 過 來, 對 前 面 提 到 的netscape 程 序, 也 可 以 通 過 編 寫 一 個script 文 件supernet 實 現 多 個 進 程 同 時 運 行:


netscape &
rm /.netscape/lock

---- 注1: 還 有 一 種 方 法, 只 適 用 普 通 用 戶: 在creat 創 建 一 個 新 文 件 時, 即 使 權 限 實 參(permission argument) 不 允 許 寫, 該 文 件 也 被 打 開 用 作 寫。 但creat 在 截 斷 一 個 現 存 文 件 時, 若 無 寫 權 限(write permission), 則 失 敗。 這 樣 就 可 以 只 通 過creat 系 統 調 用 實 現 文 件 信 號 燈 機 制。 但 這 種 做 法 有 一 個 很 明 顯 的 缺 點, 就 是 不 適 用 超 級 用 戶, 因 為 對 超 級 用 戶 沒 有 不 允 許 寫 的 東 西。

---- 注2: 這 不 適 帶& 符 號 的 台 進 程。

---- UNIX 系 統 的 文 件 信 號 燈 機 制

---- 作 為 一 個 多 用 戶、 多 任 務 的 操 作 系 統,UNIX 允 許 某 個 程 序 同 時 運 行 多 個 進 程。 但 有 時 又 由 系 統 資 源 等 因 素 的 制 約, 要 求 一 次 只 能 有 一 個 進 程 在 運 行。 例 如 在Digital UNIX 下 運 行 第 二 個Netscape 進 程 時, 系 統 報 告 如 下 錯 誤 信 息:

---- Netscape has detected a /.netscape/lock file.

---- This may indicate that another user is running Netscape using your /.netscape files.

---- 實 際 上, 第 一 個Netscape 進 程 在 運 行 時, 加 了 一 把 鎖, 禁 止 其 他Netscape 進 程 啟 動。 當 它 結 束 時, 把 鎖 打 開, 其 他 進 程 才 能 進 入。 這 就 是UNIX 的 信 號 燈 機 制。

---- 而Netscape 是 用 文 件 作 為 信 號 燈 的。 在 運 行 前, 先 檢 查 文 件/.netscape/lock 是 否 存 在: 若 存 在, 表 明 鎖 已 掛 上, 新 進 程 不 能 運 行, 只 好 等 待; 若 沒 有, 說 明 鎖 已 打 開, 可 以 運 行 了。

---- 在 掌 握 了 文 件 信 號 燈 的 機 理 , 可 以 自 行 設 計 一 套 萬 能 加 鎖 解 鎖 程 序, 為 每 個 程 序 配 上 各 自 的 鎖 和 鑰 匙。 並 且 使 用 零 字 節 長 度 的 文 件 當 鎖, 減 少 系 統 開 銷。

---- 我 們 用creat 和unlink 兩 個 系 統 調 用 實 現 加 解 鎖 和 檢 測 操 作。 一 個 進 程 運 行 之 前, 先 通 過unlink 檢 測 鎖 文 件 是 否 存 在 注1。unlink 系 統 調 用 從 一 個 目 錄 中 刪 去 一 個 文 件 鏈, 若 成 功 則 返 回0, 表 示 確 有 文 件 存 在; 若 失 敗, 表 明 文 件 不 存 在, 返 回-1。 如 果 還 沒 有 上 鎖, 就 要 用creat 系 統 調 用 創 建 鎖 文 件; 若 鎖 已 掛 上, 雖 然 進 程 並 未 運 行, 但 unlink 無 疑 會 刪 除 鎖 文 件, 所 以 也 要 用creat 來 恢 復。creat 系 統 調 用 創 建 一 個 新 文 件, 函 數 標 題 如 下:


int creat(path, perms) /* create file */
char *path; /* path name */
int perms; /* permission bits */

---- 其 中path 表 示 路 徑 加 文 件 名,perms 是10 位 的 文 件 權 限 描 述 字, 在 加 鎖 程 序 中 取0。 文 件 在 剛 創 建 時, 初 始 長 度 為 零 字 節, 用 它 來 做 鎖 文 件, 可 以 最 大 限 度 地 降 低 系 統 開 銷。

---- 鎖 文 件 規 定 為: 源 文 件 名+“.lok”。 這 樣 一 來, 就 真 正 做 到 了 一 個 程 序 配 一 把 鎖。

---- 下 面 就 列 出 加 鎖 和 解 鎖 的 程 序 清 單。 我 們 用 同 樣 的 程 序 完 成 這 兩 種 完 全 互 斥 的 操 作, 區 別 在 命 令 名 的 不 同。 在C 語 言 源 程 序 裡, 變 量argv[0] 表 示 命 令 名,“lockf” 是 上 鎖,“unlockf” 是 解 鎖。

---- 程 序LOCKF.C 暨UNLOCKF.C 的 源 代 碼


#include < stdio.h >
#include < errno.h >
#include < fcntl.h >
#include < cdatyp.h >
void syserr(msg) /*打印系統調用錯誤信息並中止 */
char *msg;
{
extern int errno, sys_nerr;
extern char *sys_errlist[];

fprintf(stderr, "ERROR: %s (%d", msg, errno);
if (errno >0 && errno< sys_nerr)
fprintf(stderr, "; %s)\n", sys_errlist[errno]);
else
fprintf(stderr, ")\n");
exit(1);
}
short nlock(name) /*上鎖過程 */
char *name;
{ char *path, *lockpath();
int fd, tries;
extern int errno;
short unlink_result;

path=lockpath(name); /*制鎖 */
unlink_result=unlink(path); /*判斷是否已經上鎖 */
fd=creat(path, 0); /*上鎖 */
if (fd==-1 || close(fd)==-1)
syserr("nlock");
if (unlink_result==-1)
return 0xff;
return (0);
}
void nunlock(name) /*解鎖 */
char *name;
{ char *lockpath();
if (unlink(lockpath(name))==-1)
syserr("nunlock");
}
static char *lockpath(name) /*制鎖的過程 */
char *name;
{ static char path[20];
char *strcat();

strcpy(path, name);
return(strcat(path, ".lok"));
}
int main(argc, argv)
int argc;
char *argv[];
{ if (argc!=2)
{ printf("Usage: %s filename\n\r", argv[0]);
return(1);
}
if (strcmp(argv[0], "lockf")==0)
if (!nlock(argv[1]))
{ printf("You can not add the same lock twice!\r\n");
return(2);
}
if (strcmp(argv[0], "unlockf")==0)
nunlock(argv[1]);
return(0);
}
本程序的用法是:
lockf 源文件名

unlockf 源文件名

---- 要 真 正 實 現 信 號 燈 機 制, 我 們 還 必 須 準 備 一 個 簡 單 的script 文 件signal:


if lockf $1
$1 注2
unlockf
else
echo “Error: Another $1 is running.”
fi

---- 這 樣 我 們 在 運 行 文 本 編 輯 器dtpad 時, 輸 入 下 列 命 令:

---- signal dtpad

---- 反 過 來, 對 前 面 提 到 的netscape 程 序, 也 可 以 通 過 編 寫 一 個script 文 件supernet 實 現 多 個 進 程 同 時 運 行:


netscape &
rm /.netscape/lock

---- 注1: 還 有 一 種 方 法, 只 適 用 普 通 用 戶: 在creat 創 建 一 個 新 文 件 時, 即 使 權 限 實 參(permission argument) 不 允 許 寫, 該 文 件 也 被 打 開 用 作 寫。 但creat 在 截 斷 一 個 現 存 文 件 時, 若 無 寫 權 限(write permission), 則 失 敗。 這 樣 就 可 以 只 通 過creat 系 統 調 用 實 現 文 件 信 號 燈 機 制。 但 這 種 做 法 有 一 個 很 明 顯 的 缺 點, 就 是 不 適 用 超 級 用 戶, 因 為 對 超 級 用 戶 沒 有 不 允 許 寫 的 東 西。

---- 注2: 這 不 適 帶& 符 號 的 台 進 程。

---- UNIX 系 統 的 文 件 信 號 燈 機 制

---- 作 為 一 個 多 用 戶、 多 任 務 的 操 作 系 統,UNIX 允 許 某 個 程 序 同 時 運 行 多 個 進 程。 但 有 時 又 由 系 統 資 源 等 因 素 的 制 約, 要 求 一 次 只 能 有 一 個 進 程 在 運 行。 例 如 在Digital UNIX 下 運 行 第 二 個Netscape 進 程 時, 系 統 報 告 如 下 錯 誤 信 息:

---- Netscape has detected a /.netscape/lock file.

---- This may indicate that another user is running Netscape using your /.netscape files.

---- 實 際 上, 第 一 個Netscape 進 程 在 運 行 時, 加 了 一 把 鎖, 禁 止 其 他Netscape 進 程 啟 動。 當 它 結 束 時, 把 鎖 打 開, 其 他 進 程 才 能 進 入。 這 就 是UNIX 的 信 號 燈 機 制。

---- 而Netscape 是 用 文 件 作 為 信 號 燈 的。 在 運 行 前, 先 檢 查 文 件/.netscape/lock 是 否 存 在: 若 存 在, 表 明 鎖 已 掛 上, 新 進 程 不 能 運 行, 只 好 等 待; 若 沒 有, 說 明 鎖 已 打 開, 可 以 運 行 了。

---- 在 掌 握 了 文 件 信 號 燈 的 機 理 , 可 以 自 行 設 計 一 套 萬 能 加 鎖 解 鎖 程 序, 為 每 個 程 序 配 上 各 自 的 鎖 和 鑰 匙。 並 且 使 用 零 字 節 長 度 的 文 件 當 鎖, 減 少 系 統 開 銷。

---- 我 們 用creat 和unlink 兩 個 系 統 調 用 實 現 加 解 鎖 和 檢 測 操 作。 一 個 進 程 運 行 之 前, 先 通 過unlink 檢 測 鎖 文 件 是 否 存 在 注1。unlink 系 統 調 用 從 一 個 目 錄 中 刪 去 一 個 文 件 鏈, 若 成 功 則 返 回0, 表 示 確 有 文 件 存 在; 若 失 敗, 表 明 文 件 不 存 在, 返 回-1。 如 果 還 沒 有 上 鎖, 就 要 用creat 系 統 調 用 創 建 鎖 文 件; 若 鎖 已 掛 上, 雖 然 進 程 並 未 運 行, 但 unlink 無 疑 會 刪 除 鎖 文 件, 所 以 也 要 用creat 來 恢 復。creat 系 統 調 用 創 建 一 個 新 文 件, 函 數 標 題 如 下:


int creat(path, perms) /* create file */
char *path; /* path name */
int perms; /* permission bits */

---- 其 中path 表 示 路 徑 加 文 件 名,perms 是10 位 的 文 件 權 限 描 述 字, 在 加 鎖 程 序 中 取0。 文 件 在 剛 創 建 時, 初 始 長 度 為 零 字 節, 用 它 來 做 鎖 文 件, 可 以 最 大 限 度 地 降 低 系 統 開 銷。
---- 鎖 文 件 規 定 為: 源 文 件 名+“.lok”。 這 樣 一 來, 就 真 正 做 到 了 一 個 程 序 配 一 把 鎖。

---- 下 面 就 列 出 加 鎖 和 解 鎖 的 程 序 清 單。 我 們 用 同 樣 的 程 序 完 成 這 兩 種 完 全 互 斥 的 操 作, 區 別 在 命 令 名 的 不 同。 在C 語 言 源 程 序 裡, 變 量argv[0] 表 示 命 令 名,“lockf” 是 上 鎖,“unlockf” 是 解 鎖。

---- 程 序LOCKF.C 暨UNLOCKF.C 的 源 代 碼 #include < stdio.h > #include < errno.h > #include < fcntl.h > #include < cdatyp.h > void syserr(msg) /*打印系統調用錯誤信息並中止 */ char *msg; { extern int errno, sys_nerr; extern char *sys_errlist[]; fprintf(stderr, "ERROR: %s (%d", msg, errno); if (errno >0 && errno< sys_nerr) fprintf(stderr, "; %s)\n", sys_errlist[errno]); else fprintf(stderr, ")\n"); exit(1); } short nlock(name) /*上鎖過程 */ char *name; { char *path, *lockpath(); int fd, tries; extern int errno; short unlink_result; path=lockpath(name); /*制鎖 */ unlink_result=unlink(path); /*判斷是否已經上鎖 */ fd=creat(path, 0); /*上鎖 */ if (fd==-1 || close(fd)==-1) syserr("nlock"); if (unlink_result==-1) return 0xff; return (0); } void nunlock(name) /*解鎖 */ char *name; { char *lockpath(); if (unlink(lockpath(name))==-1) syserr("nunlock"); } static char *lockpath(name) /*制鎖的過程 */ char *name; { static char path[20]; char *strcat(); strcpy(path, name); return(strcat(path, ".lok")); } int main(argc, argv) int argc; char *argv[]; { if (argc!=2) { printf("Usage: %s filename\n\r", argv[0]); return(1); } if (strcmp(argv[0], "lockf")==0) if (!nlock(argv[1])) { printf("You can not add the same lock twice!\r\n"); return(2); } if (strcmp(argv[0], "unlockf")==0) nunlock(argv[1]); return(0); } 本程序的用法是: lockf 源文件名 或 unlockf 源文件名

---- 要 真 正 實 現 信 號 燈 機 制, 我 們 還 必 須 準 備 一 個 簡 單 的script 文 件signal:


if lockf $1
$1 注2
unlockf
else
echo “Error: Another $1 is running.”
fi

---- 這 樣 我 們 在 運 行 文 本 編 輯 器dtpad 時, 輸 入 下 列 命 令:

---- signal dtpad

---- 反 過 來, 對 前 面 提 到 的netscape 程 序, 也 可 以 通 過 編 寫 一 個script 文 件supernet 實 現 多 個 進 程 同 時 運 行:


netscape &
rm /.netscape/lock

---- 注1: 還 有 一 種 方 法, 只 適 用 普 通 用 戶: 在creat 創 建 一 個 新 文 件 時, 即 使 權 限 實 參(permission argument) 不 允 許 寫, 該 文 件 也 被 打 開 用 作 寫。 但creat 在 截 斷 一 個 現 存 文 件 時, 若 無 寫 權 限(write permission), 則 失 敗。 這 樣 就 可 以 只 通 過creat 系 統 調 用 實 現 文 件 信 號 燈 機 制。 但 這 種 做 法 有 一 個 很 明 顯 的 缺 點, 就 是 不 適 用 超 級 用 戶, 因 為 對 超 級 用 戶 沒 有 不 允 許 寫 的 東 西。

---- 注2: 這 不 適 帶& 符 號 的 台 進 程。

---- UNIX 系 統 的 文 件 信 號 燈 機 制

---- 作 為 一 個 多 用 戶、 多 任 務 的 操 作 系 統,UNIX 允 許 某 個 程 序 同 時 運 行 多 個 進 程。 但 有 時 又 由 系 統 資 源 等 因 素 的 制 約, 要 求 一 次 只 能 有 一 個 進 程 在 運 行。 例 如 在Digital UNIX 下 運 行 第 二 個Netscape 進 程 時, 系 統 報 告 如 下 錯 誤 信 息:

---- Netscape has detected a /.netscape/lock file.

---- This may indicate that another user is running Netscape using your /.netscape files.

---- 實 際 上, 第 一 個Netscape 進 程 在 運 行 時, 加 了 一 把 鎖, 禁 止 其 他Netscape 進 程 啟 動。 當 它 結 束 時, 把 鎖 打 開, 其 他 進 程 才 能 進 入。 這 就 是UNIX 的 信 號 燈 機 制。

---- 而Netscape 是 用 文 件 作 為 信 號 燈 的。 在 運 行 前, 先 檢 查 文 件/.netscape/lock 是 否 存 在: 若 存 在, 表 明 鎖 已 掛 上, 新 進 程 不 能 運 行, 只 好 等 待; 若 沒 有, 說 明 鎖 已 打 開, 可 以 運 行 了。

---- 在 掌 握 了 文 件 信 號 燈 的 機 理 , 可 以 自 行 設 計 一 套 萬 能 加 鎖 解 鎖 程 序, 為 每 個 程 序 配 上 各 自 的 鎖 和 鑰 匙。 並 且 使 用 零 字 節 長 度 的 文 件 當 鎖, 減 少 系 統 開 銷。

---- 我 們 用creat 和unlink 兩 個 系 統 調 用 實 現 加 解 鎖 和 檢 測 操 作。 一 個 進 程 運 行 之 前, 先 通 過unlink 檢 測 鎖 文 件 是 否 存 在 注1。unlink 系 統 調 用 從 一 個 目 錄 中 刪 去 一 個 文 件 鏈, 若 成 功 則 返 回0, 表 示 確 有 文 件 存 在; 若 失 敗, 表 明 文 件 不 存 在, 返 回-1。 如 果 還 沒 有 上 鎖, 就 要 用creat 系 統 調 用 創 建 鎖 文 件; 若 鎖 已 掛 上, 雖 然 進 程 並 未 運 行, 但 unlink 無 疑 會 刪 除 鎖 文 件, 所 以 也 要 用creat 來 恢 復。creat 系 統 調 用 創 建 一 個 新 文 件, 函 數 標 題 如 下:


int creat(path, perms) /* create file */
char *path; /* path name */
int perms; /* permission bits */

---- 其 中path 表 示 路 徑 加 文 件 名,perms 是10 位 的 文 件 權 限 描 述 字, 在 加 鎖 程 序 中 取0。 文 件 在 剛 創 建 時, 初 始 長 度 為 零 字 節, 用 它 來 做 鎖 文 件, 可 以 最 大 限 度 地 降 低 系 統 開 銷。

---- 鎖 文 件 規 定 為: 源 文 件 名+“.lok”。 這 樣 一 來, 就 真 正 做 到 了 一 個 程 序 配 一 把 鎖。

---- 下 面 就 列 出 加 鎖 和 解 鎖 的 程 序 清 單。 我 們 用 同 樣 的 程 序 完 成 這 兩 種 完 全 互 斥 的 操 作, 區 別 在 命 令 名 的 不 同。 在C 語 言 源 程 序 裡, 變 量argv[0] 表 示 命 令 名,“lockf” 是 上 鎖,“unlockf” 是 解 鎖。

---- 程 序LOCKF.C 暨UNLOCKF.C 的 源 代 碼


#include < stdio.h >
#include < errno.h >
#include < fcntl.h >
#include < cdatyp.h >
void syserr(msg) /*打印系統調用錯誤信息並中止 */
char *msg;
{
extern int errno, sys_nerr;
extern char *sys_errlist[];

fprintf(stderr, "ERROR: %s (%d", msg, errno);
if (errno >0 && errno< sys_nerr)
fprintf(stderr, "; %s)\n", sys_errlist[errno]);
else
fprintf(stderr, ")\n");
exit(1);
}
short nlock(name) /*上鎖過程 */
char *name;
{ char *path, *lockpath();
int fd, tries;
extern int errno;
short unlink_result;

path=lockpath(name); /*制鎖 */
unlink_result=unlink(path); /*判斷是否已經上鎖 */
fd=creat(path, 0); /*上鎖 */
if (fd==-1 || close(fd)==-1)
syserr("nlock");
if (unlink_result==-1)
return 0xff;
return (0);
}
void nunlock(name) /*解鎖 */
char *name;
{ char *lockpath();
if (unlink(lockpath(name))==-1)
syserr("nunlock");
}
static char *lockpath(name) /*制鎖的過程 */
char *name;
{ static char path[20];
char *strcat();

strcpy(path, name);
return(strcat(path, ".lok"));
}
int main(argc, argv)
int argc;
char *argv[];
{ if (argc!=2)
{ printf("Usage: %s filename\n\r", argv[0]);
return(1);
}
if (strcmp(argv[0], "lockf")==0)
if (!nlock(argv[1]))
{ printf("You can not add the same lock twice!\r\n");
return(2);
}
if (strcmp(argv[0], "unlockf")==0)
nunlock(argv[1]);
return(0);
}
本程序的用法是:
lockf 源文件名

unlockf 源文件名

---- 要 真 正 實 現 信 號 燈 機 制, 我 們 還 必 須 準 備 一 個 簡 單 的script 文 件signal: if lockf $1 $1 注2 unlockf else echo “Error: Another $1 is running.” fi

---- 這 樣 我 們 在 運 行 文 本 編 輯 器dtpad 時, 輸 入 下 列 命 令:

---- signal dtpad

---- 反 過 來, 對 前 面 提 到 的netscape 程 序, 也 可 以 通 過 編 寫 一 個script 文 件supernet 實 現 多 個 進 程 同 時 運 行:


netscape &
rm /.netscape/lock

---- 注1: 還 有 一 種 方 法, 只 適 用 普 通 用 戶: 在creat 創 建 一 個 新 文 件 時, 即 使 權 限 實 參(permission argument) 不 允 許 寫, 該 文 件 也 被 打 開 用 作 寫。 但creat 在 截 斷 一 個 現 存 文 件 時, 若 無 寫 權 限(write permission), 則 失 敗。 這 樣 就 可 以 只 通 過creat 系 統 調 用 實 現 文 件 信 號 燈 機 制。 但 這 種 做 法 有 一 個 很 明 顯 的 缺 點, 就 是 不 適 用 超 級 用 戶, 因 為 對 超 級 用 戶 沒 有 不 允 許 寫 的 東 西。

---- 注2: 這 不 適 帶& 符 號 的 台 進 程。

---- UNIX 系 統 的 文 件 信 號 燈 機 制

---- 作 為 一 個 多 用 戶、 多 任 務 的 操 作 系 統,UNIX 允 許 某 個 程 序 同 時 運 行 多 個 進 程。 但 有 時 又 由 系 統 資 源 等 因 素 的 制 約, 要 求 一 次 只 能 有 一 個 進 程 在 運 行。 例 如 在Digital UNIX 下 運 行 第 二 個Netscape 進 程 時, 系 統 報 告 如 下 錯 誤 信 息:

---- Netscape has detected a /.netscape/lock file.

---- This may indicate that another user is running Netscape using your /.netscape files.

---- 實 際 上, 第 一 個Netscape 進 程 在 運 行 時, 加 了 一 把 鎖, 禁 止 其 他Netscape 進 程 啟 動。 當 它 結 束 時, 把 鎖 打 開, 其 他 進 程 才 能 進 入。 這 就 是UNIX 的 信 號 燈 機 制。

---- 而Netscape 是 用 文 件 作 為 信 號 燈 的。 在 運 行 前, 先 檢 查 文 件/.netscape/lock 是 否 存 在: 若 存 在, 表 明 鎖 已 掛 上, 新 進 程 不 能 運 行, 只 好 等 待; 若 沒 有, 說 明 鎖 已 打 開, 可 以 運 行 了。

---- 在 掌 握 了 文 件 信 號 燈 的 機 理 , 可 以 自 行 設 計 一 套 萬 能 加 鎖 解 鎖 程 序, 為 每 個 程 序 配 上 各 自 的 鎖 和 鑰 匙。 並 且 使 用 零 字 節 長 度 的 文 件 當 鎖, 減 少 系 統 開 銷。

---- 我 們 用creat 和unlink 兩 個 系 統 調 用 實 現 加 解 鎖 和 檢 測 操 作。 一 個 進 程 運 行 之 前, 先 通 過unlink 檢 測 鎖 文 件 是 否 存 在 注1。unlink 系 統 調 用 從 一 個 目 錄 中 刪 去 一 個 文 件 鏈, 若 成 功 則 返 回0, 表 示 確 有 文 件 存 在; 若 失 敗, 表 明 文 件 不 存 在, 返 回-1。 如 果 還 沒 有 上 鎖, 就 要 用creat 系 統 調 用 創 建 鎖 文 件; 若 鎖 已 掛 上, 雖 然 進 程 並 未 運 行, 但 unlink 無 疑 會 刪 除 鎖 文 件, 所 以 也 要 用creat 來 恢 復。creat 系 統 調 用 創 建 一 個 新 文 件, 函 數 標 題 如 下:


int creat(path, perms) /* create file */
char *path; /* path name */
int perms; /* permission bits */

---- 其 中path 表 示 路 徑 加 文 件 名,perms 是10 位 的 文 件 權 限 描 述 字, 在 加 鎖 程 序 中 取0。 文 件 在 剛 創 建 時, 初 始 長 度 為 零 字 節, 用 它 來 做 鎖 文 件, 可 以 最 大 限 度 地 降 低 系 統 開 銷。

---- 鎖 文 件 規 定 為: 源 文 件 名+“.lok”。 這 樣 一 來, 就 真 正 做 到 了 一 個 程 序 配 一 把 鎖。

---- 下 面 就 列 出 加 鎖 和 解 鎖 的 程 序 清 單。 我 們 用 同 樣 的 程 序 完 成 這 兩 種 完 全 互 斥 的 操 作, 區 別 在 命 令 名 的 不 同。 在C 語 言 源 程 序 裡, 變 量argv[0] 表 示 命 令 名,“lockf” 是 上 鎖,“unlockf” 是 解 鎖。

---- 程 序LOCKF.C 暨UNLOCKF.C 的 源 代 碼


#include < stdio.h >
#include < errno.h >
#include < fcntl.h >
#include < cdatyp.h >
void syserr(msg) /*打印系統調用錯誤信息並中止 */
char *msg;
{
extern int errno, sys_nerr;
extern char *sys_errlist[];

fprintf(stderr, "ERROR: %s (%d", msg, errno);
if (errno >0 && errno< sys_nerr)
fprintf(stderr, "; %s)\n", sys_errlist[errno]);
else
fprintf(stderr, ")\n");
exit(1);
}
short nlock(name) /*上鎖過程 */
char *name;
{ char *path, *lockpath();
int fd, tries;
extern int errno;
short unlink_result;

path=lockpath(name); /*制鎖 */
unlink_result=unlink(path); /*判斷是否已經上鎖 */
fd=creat(path, 0); /*上鎖 */
if (fd==-1 || close(fd)==-1)
syserr("nlock");
if (unlink_result==-1)
return 0xff;
return (0);
}
void nunlock(name) /*解鎖 */
char *name;
{ char *lockpath();
if (unlink(lockpath(name))==-1)
syserr("nunlock");
}
static char *lockpath(name) /*制鎖的過程 */
char *name;
{ static char path[20];
char *strcat();

strcpy(path, name);
return(strcat(path, ".lok"));
}
int main(argc, argv)
int argc;
char *argv[];
{ if (argc!=2)
{ printf("Usage: %s filename\n\r", argv[0]);
return(1);
}
if (strcmp(argv[0], "lockf")==0)
if (!nlock(argv[1]))
{ printf("You can not add the same lock twice!\r\n");
return(2);
}
if (strcmp(argv[0], "unlockf")==0)
nunlock(argv[1]);
return(0);
}
本程序的用法是:
lockf 源文件名

unlockf 源文件名

---- 要 真 正 實 現 信 號 燈 機 制, 我 們 還 必 須 準 備 一 個 簡 單 的script 文 件signal:


if lockf $1
$1 注2
unlockf
else
echo “Error: Another $1 is running.”
fi

---- 這 樣 我 們 在 運 行 文 本 編 輯 器dtpad 時, 輸 入 下 列 命 令:

---- signal dtpad

---- 反 過 來, 對 前 面 提 到 的netscape 程 序, 也 可 以 通 過 編 寫 一 個script 文 件supernet 實 現 多 個 進 程 同 時 運 行:


netscape &
rm /.netscape/lock

---- 注1: 還 有 一 種 方 法, 只 適 用 普 通 用 戶: 在creat 創 建 一 個 新 文 件 時, 即 使 權 限 實 參(permission argument) 不 允 許 寫, 該 文 件 也 被 打 開 用 作 寫。 但creat 在 截 斷 一 個 現 存 文 件 時, 若 無 寫 權 限(write permission), 則 失 敗。 這 樣 就 可 以 只 通 過creat 系 統 調 用 實 現 文 件 信 號 燈 機 制。 但 這 種 做 法 有 一 個 很 明 顯 的 缺 點, 就 是 不 適 用 超 級 用 戶, 因 為 對 超 級 用 戶 沒 有 不 允 許 寫 的 東 西。

---- 注2: 這 不 適 帶& 符 號 的 台 進 程。

---- UNIX 系 統 的 文 件 信 號 燈 機 制

---- 作 為 一 個 多 用 戶、 多 任 務 的 操 作 系 統,UNIX 允 許 某 個 程 序 同 時 運 行 多 個 進 程。 但 有 時 又 由 系 統 資 源 等 因 素 的 制 約, 要 求 一 次 只 能 有 一 個 進 程 在 運 行。 例 如 在Digital UNIX 下 運 行 第 二 個Netscape 進 程 時, 系 統 報 告 如 下 錯 誤 信 息:

---- Netscape has detected a /.netscape/lock file.

---- This may indicate that another user is running Netscape using your /.netscape files.

---- 實 際 上, 第 一 個Netscape 進 程 在 運 行 時, 加 了 一 把 鎖, 禁 止 其 他Netscape 進 程 啟 動。 當 它 結 束 時, 把 鎖 打 開, 其 他 進 程 才 能 進 入。 這 就 是UNIX 的 信 號 燈 機 制。

---- 而Netscape 是 用 文 件 作 為 信 號 燈 的。 在 運 行 前, 先 檢 查 文 件/.netscape/lock 是 否 存 在: 若 存 在, 表 明 鎖 已 掛 上, 新 進 程 不 能 運 行, 只 好 等 待; 若 沒 有, 說 明 鎖 已 打 開, 可 以 運 行 了。

---- 在 掌 握 了 文 件 信 號 燈 的 機 理 , 可 以 自 行 設 計 一 套 萬 能 加 鎖 解 鎖 程 序, 為 每 個 程 序 配 上 各 自 的 鎖 和 鑰 匙。 並 且 使 用 零 字 節 長 度 的 文 件 當 鎖, 減 少 系 統 開 銷。

---- 我 們 用creat 和unlink 兩 個 系 統 調 用 實 現 加 解 鎖 和 檢 測 操 作。 一 個 進 程 運 行 之 前, 先 通 過unlink 檢 測 鎖 文 件 是 否 存 在 注1。unlink 系 統 調 用 從 一 個 目 錄 中 刪 去 一 個 文 件 鏈, 若 成 功 則 返 回0, 表 示 確 有 文 件 存 在; 若 失 敗, 表 明 文 件 不 存 在, 返 回-1。 如 果 還 沒 有 上 鎖, 就 要 用creat 系 統 調 用 創 建 鎖 文 件; 若 鎖 已 掛 上, 雖 然 進 程 並 未 運 行, 但 unlink 無 疑 會 刪 除 鎖 文 件, 所 以 也 要 用creat 來 恢 復。creat 系 統 調 用 創 建 一 個 新 文 件, 函 數 標 題 如 下:


int creat(path, perms) /* create file */
char *path; /* path name */
int perms; /* permission bits */

---- 其 中path 表 示 路 徑 加 文 件 名,perms 是10 位 的 文 件 權 限 描 述 字, 在 加 鎖 程 序 中 取0。 文 件 在 剛 創 建 時, 初 始 長 度 為 零 字 節, 用 它 來 做 鎖 文 件, 可 以 最 大 限 度 地 降 低 系 統 開 銷。

---- 鎖 文 件 規 定 為: 源 文 件 名+“.lok”。 這 樣 一 來, 就 真 正 做 到 了 一 個 程 序 配 一 把 鎖。

---- 下 面 就 列 出 加 鎖 和 解 鎖 的 程 序 清 單。 我 們 用 同 樣 的 程 序 完 成 這 兩 種 完 全 互 斥 的 操 作, 區 別 在 命 令 名 的 不 同。 在C 語 言 源 程 序 裡, 變 量argv[0] 表 示 命 令 名,“lockf” 是 上 鎖,“unlockf” 是 解 鎖。

---- 程 序LOCKF.C 暨UNLOCKF.C 的 源 代 碼

#include < stdio.h >
#include < errno.h >
#include < fcntl.h >
#include < cdatyp.h >
void syserr(msg) /*打印系統調用錯誤信息並中止 */
char *msg;
{
extern int errno, sys_nerr;
extern char *sys_errlist[];

fprintf(stderr, "ERROR: %s (%d", msg, errno);
if (errno >0 && errno< sys_nerr)
fprintf(stderr, "; %s)\n", sys_errlist[errno]);
else
fprintf(stderr, ")\n");
exit(1);
}
short nlock(name) /*上鎖過程 */
char *name;
{ char *path, *lockpath();
int fd, tries;
extern int errno;
short unlink_result;

path=lockpath(name); /*制鎖 */
unlink_result=unlink(path); /*判斷是否已經上鎖 */
fd=creat(path, 0); /*上鎖 */
if (fd==-1 || close(fd)==-1)
syserr("nlock");
if (unlink_result==-1)
return 0xff;
return (0);
}
void nunlock(name) /*解鎖 */
char *name;
{ char *lockpath();
if (unlink(lockpath(name))==-1)
syserr("nunlock");
}
static char *lockpath(name) /*制鎖的過程 */
char *name;
{ static char path[20];
char *strcat();

strcpy(path, name);
return(strcat(path, ".lok"));
}
int main(argc, argv)
int argc;
char *argv[];
{ if (argc!=2)
{ printf("Usage: %s filename\n\r", argv[0]);
return(1);
}
if (strcmp(argv[0], "lockf")==0)
if (!nlock(argv[1]))
{ printf("You can not add the same lock twice!\r\n");
return(2);
}
if (strcmp(argv[0], "unlockf")==0)
nunlock(argv[1]);
return(0);
}
本程序的用法是:
lockf 源文件名

unlockf 源文件名

---- 要 真 正 實 現 信 號 燈 機 制, 我 們 還 必 須 準 備 一 個 簡 單 的script 文 件signal:


if lockf $1
$1 注2
unlockf
else
echo “Error: Another $1 is running.”
fi

---- 這 樣 我 們 在 運 行 文 本 編 輯 器dtpad 時, 輸 入 下 列 命 令:

---- signal dtpad

---- 反 過 來, 對 前 面 提 到 的netscape 程 序, 也 可 以 通 過 編 寫 一 個script 文 件supernet 實 現 多 個 進 程 同 時 運 行:


netscape &
rm /.netscape/lock

---- 注1: 還 有 一 種 方 法, 只 適 用 普 通 用 戶: 在creat 創 建 一 個 新 文 件 時, 即 使 權 限 實 參(permission argument) 不 允 許 寫, 該 文 件 也 被 打 開 用 作 寫。 但creat 在 截 斷 一 個 現 存 文 件 時, 若 無 寫 權 限(write permission), 則 失 敗。 這 樣 就 可 以 只 通 過creat 系 統 調 用 實 現 文 件 信 號 燈 機 制。 但 這 種 做 法 有 一 個 很 明 顯 的 缺 點, 就 是 不 適 用 超 級 用 戶, 因 為 對 超 級 用 戶 沒 有 不 允 許 寫 的 東 西。

---- 注2: 這 不 適 帶& 符 號 的 台 進 程。

---- UNIX 系 統 的 文 件 信 號 燈 機 制

---- 作 為 一 個 多 用 戶、 多 任 務 的 操 作 系 統,UNIX 允 許 某 個 程 序 同 時 運 行 多 個 進 程。 但 有 時 又 由 系 統 資 源 等 因 素 的 制 約, 要 求 一 次 只 能 有 一 個 進 程 在 運 行。 例 如 在Digital UNIX 下 運 行 第 二 個Netscape 進 程 時, 系 統 報 告 如 下 錯 誤 信 息:

---- Netscape has detected a /.netscape/lock file.

---- This may indicate that another user is running Netscape using your /.netscape files.

---- 實 際 上, 第 一 個Netscape 進 程 在 運 行 時, 加 了 一 把 鎖, 禁 止 其 他Netscape 進 程 啟 動。 當 它 結 束 時, 把 鎖 打 開, 其 他 進 程 才 能 進 入。 這 就 是UNIX 的 信 號 燈 機 制。

---- 而Netscape 是 用 文 件 作 為 信 號 燈 的。 在 運 行 前, 先 檢 查 文 件/.netscape/lock 是 否 存 在: 若 存 在, 表 明 鎖 已 掛 上, 新 進 程 不 能 運 行, 只 好 等 待; 若 沒 有, 說 明 鎖 已 打 開, 可 以 運 行 了。

---- 在 掌 握 了 文 件 信 號 燈 的 機 理 , 可 以 自 行 設 計 一 套 萬 能 加 鎖 解 鎖 程 序, 為 每 個 程 序 配 上 各 自 的 鎖 和 鑰 匙。 並 且 使 用 零 字 節 長 度 的 文 件 當 鎖, 減 少 系 統 開 銷。

---- 我 們 用creat 和unlink 兩 個 系 統 調 用 實 現 加 解 鎖 和 檢 測 操 作。 一 個 進 程 運 行 之 前, 先 通 過unlink 檢 測 鎖 文 件 是 否 存 在 注1。unlink 系 統 調 用 從 一 個 目 錄 中 刪 去 一 個 文 件 鏈, 若 成 功 則 返 回0, 表 示 確 有 文 件 存 在; 若 失 敗, 表 明 文 件 不 存 在, 返 回-1。 如 果 還 沒 有 上 鎖, 就 要 用creat 系 統 調 用 創 建 鎖 文 件; 若 鎖 已 掛 上, 雖 然 進 程 並 未 運 行, 但 unlink 無 疑 會 刪 除 鎖 文 件, 所 以 也 要 用creat 來 恢 復。creat 系 統 調 用 創 建 一 個 新 文 件, 函 數 標 題 如 下:


int creat(path, perms) /* create file */
char *path; /* path name */
int perms; /* permission bits */

---- 其 中path 表 示 路 徑 加 文 件 名,perms 是10 位 的 文 件 權 限 描 述 字, 在 加 鎖 程 序 中 取0。 文 件 在 剛 創 建 時, 初 始 長 度 為 零 字 節, 用 它 來 做 鎖 文 件, 可 以 最 大 限 度 地 降 低 系 統 開 銷。

---- 鎖 文 件 規 定 為: 源 文 件 名+“.lok”。 這 樣 一 來, 就 真 正 做 到 了 一 個 程 序 配 一 把 鎖。

---- 下 面 就 列 出 加 鎖 和 解 鎖 的 程 序 清 單。 我 們 用 同 樣 的 程 序 完 成 這 兩 種 完 全 互 斥 的 操 作, 區 別 在 命 令 名 的 不 同。 在C 語 言 源 程 序 裡, 變 量argv[0] 表 示 命 令 名,“lockf” 是 上 鎖,“unlockf” 是 解 鎖。

---- 程 序LOCKF.C 暨UNLOCKF.C 的 源 代 碼


#include < stdio.h >
#include < errno.h >
#include < fcntl.h >
#include < cdatyp.h >
void syserr(msg) /*打印系統調用錯誤信息並中止 */
char *msg;
{
extern int errno, sys_nerr;
extern char *sys_errlist[];

fprintf(stderr, "ERROR: %s (%d", msg, errno);
if (errno >0 && errno< sys_nerr)
fprintf(stderr, "; %s)\n", sys_errlist[errno]);
else
fprintf(stderr, ")\n");
exit(1);
}
short nlock(name) /*上鎖過程 */
char *name;
{ char *path, *lockpath();
int fd, tries;
extern int errno;
short unlink_result;

path=lockpath(name); /*制鎖 */
unlink_result=unlink(path); /*判斷是否已經上鎖 */
fd=creat(path, 0); /*上鎖 */
if (fd==-1 || close(fd)==-1)
syserr("nlock");
if (unlink_result==-1)
return 0xff;
return (0);
}
void nunlock(name) /*解鎖 */
char *name;
{ char *lockpath();
if (unlink(lockpath(name))==-1)
syserr("nunlock");
}
static char *lockpath(name) /*制鎖的過程 */
char *name;
{ static char path[20];
char *strcat();

strcpy(path, name);
return(strcat(path, ".lok"));
}
int main(argc, argv)
int argc;
char *argv[];
{ if (argc!=2)
{ printf("Usage: %s filename\n\r", argv[0]);
return(1);
}
if (strcmp(argv[0], "lockf")==0)
if (!nlock(argv[1]))
{ printf("You can not add the same lock twice!\r\n");
return(2);
}
if (strcmp(argv[0], "unlockf")==0)
nunlock(argv[1]);
return(0);
}
本程序的用法是:
lockf 源文件名

unlockf 源文件名

---- 要 真 正 實 現 信 號 燈 機 制, 我 們 還 必 須 準 備 一 個 簡 單 的script 文 件signal:


if lockf $1
$1 注2
unlockf
else
echo “Error: Another $1 is running.”
fi

---- 這 樣 我 們 在 運 行 文 本 編 輯 器dtpad 時, 輸 入 下 列 命 令:

---- signal dtpad

---- 反 過 來, 對 前 面 提 到 的netscape 程 序, 也 可 以 通 過 編 寫 一 個script 文 件supernet 實 現 多 個 進 程 同 時 運 行:


netscape &
rm /.netscape/lock

---- 注1: 還 有 一 種 方 法, 只 適 用 普 通 用 戶: 在creat 創 建 一 個 新 文 件 時, 即 使 權 限 實 參(permission argument) 不 允 許 寫, 該 文 件 也 被 打 開 用 作 寫。 但creat 在 截 斷 一 個 現 存 文 件 時, 若 無 寫 權 限(write permission), 則 失 敗。 這 樣 就 可 以 只 通 過creat 系 統 調 用 實 現 文 件 信 號 燈 機 制。 但 這 種 做 法 有 一 個 很 明 顯 的 缺 點, 就 是 不 適 用 超 級 用 戶, 因 為 對 超 級 用 戶 沒 有 不 允 許 寫 的 東 西。

---- 注2: 這 不 適 帶& 符 號 的 台 進 程。

---- UNIX 系 統 的 文 件 信 號 燈 機 制

---- 作 為 一 個 多 用 戶、 多 任 務 的 操 作 系 統,UNIX 允 許 某 個 程 序 同 時 運 行 多 個 進 程。 但 有 時 又 由 系 統 資 源 等 因 素 的 制 約, 要 求 一 次 只 能 有 一 個 進 程 在 運 行。 例 如 在Digital UNIX 下 運 行 第 二 個Netscape 進 程 時, 系 統 報 告 如 下 錯 誤 信 息:

---- Netscape has detected a /.netscape/lock file.

---- This may indicate that another user is running Netscape using your /.netscape files.

---- 實 際 上, 第 一 個Netscape 進 程 在 運 行 時, 加 了 一 把 鎖, 禁 止 其 他Netscape 進 程 啟 動。 當 它 結 束 時, 把 鎖 打 開, 其 他 進 程 才 能 進 入。 這 就 是UNIX 的 信 號 燈 機 制。

---- 而Netscape 是 用 文 件 作 為 信 號 燈 的。 在 運 行 前, 先 檢 查 文 件/.netscape/lock 是 否 存 在: 若 存 在, 表 明 鎖 已 掛 上, 新 進 程 不 能 運 行, 只 好 等 待; 若 沒 有, 說 明 鎖 已 打 開, 可 以 運 行 了。

---- 在 掌 握 了 文 件 信 號 燈 的 機 理 , 可 以 自 行 設 計 一 套 萬 能 加 鎖 解 鎖 程 序, 為 每 個 程 序 配 上 各 自 的 鎖 和 鑰 匙。 並 且 使 用 零 字 節 長 度 的 文 件 當 鎖, 減 少 系 統 開 銷。

---- 我 們 用creat 和unlink 兩 個 系 統 調 用 實 現 加 解 鎖 和 檢 測 操 作。 一 個 進 程 運 行 之 前, 先 通 過unlink 檢 測 鎖 文 件 是 否 存 在 注1。unlink 系 統 調 用 從 一 個 目 錄 中 刪 去 一 個 文 件 鏈, 若 成 功 則 返 回0, 表 示 確 有 文 件 存 在; 若 失 敗, 表 明 文 件 不 存 在, 返 回-1。 如 果 還 沒 有 上 鎖, 就 要 用creat 系 統 調 用 創 建 鎖 文 件; 若 鎖 已 掛 上, 雖 然 進 程 並 未 運 行, 但 unlink 無 疑 會 刪 除 鎖 文 件, 所 以 也 要 用creat 來 恢 復。creat 系 統 調 用 創 建 一 個 新 文 件, 函 數 標 題 如 下:


int creat(path, perms) /* create file */
char *path; /* path name */
int perms; /* permission bits */

---- 其 中path 表 示 路 徑 加 文 件 名,perms 是10 位 的 文 件 權 限 描 述 字, 在 加 鎖 程 序 中 取0。 文 件 在 剛 創 建 時, 初 始 長 度 為 零 字 節, 用 它 來 做 鎖 文 件, 可 以 最 大 限 度 地 降 低 系 統 開 銷。

---- 鎖 文 件 規 定 為: 源 文 件 名+“.lok”。 這 樣 一 來, 就 真 正 做 到 了 一 個 程 序 配 一 把 鎖。

---- 下 面 就 列 出 加 鎖 和 解 鎖 的 程 序 清 單。 我 們 用 同 樣 的 程 序 完 成 這 兩 種 完 全 互 斥 的 操 作, 區 別 在 命 令 名 的 不 同。 在C 語 言 源 程 序 裡, 變 量argv[0] 表 示 命 令 名,“lockf” 是 上 鎖,“unlockf” 是 解 鎖。

---- 程 序LOCKF.C 暨UNLOCKF.C 的 源 代 碼


#include < stdio.h >
#include < errno.h >
#include < fcntl.h >
#include < cdatyp.h >
void syserr(msg) /*打印系統調用錯誤信息並中止 */
char *msg;
{
extern int errno, sys_nerr;
extern char *sys_errlist[];

fprintf(stderr, "ERROR: %s (%d", msg, errno);
if (errno >0 && errno< sys_nerr)
fprintf(stderr, "; %s)\n", sys_errlist[errno]);
else
fprintf(stderr, ")\n");
exit(1);
}
short nlock(name) /*上鎖過程 */
char *name;
{ char *path, *lockpath();
int fd, tries;
extern int errno;
short unlink_result;

path=lockpath(name); /*制鎖 */
unlink_result=unlink(path); /*判斷是否已經上鎖 */
fd=creat(path, 0); /*上鎖 */
if (fd==-1 || close(fd)==-1)
syserr("nlock");
if (unlink_result==-1)
return 0xff;
return (0);
}
void nunlock(name) /*解鎖 */
char *name;
{ char *lockpath();
if (unlink(lockpath(name))==-1)
syserr("nunlock");
}
static char *lockpath(name) /*制鎖的過程 */
char *name;
{ static char path[20];
char *strcat();

strcpy(path, name);
return(strcat(path, ".lok"));
}
int main(argc, argv)
int argc;
char *argv[];
{ if (argc!=2)
{ printf("Usage: %s filename\n\r", argv[0]);
return(1);
}
if (strcmp(argv[0], "lockf")==0)
if (!nlock(argv[1]))
{ printf("You can not add the same lock twice!\r\n");
return(2);
}
if (strcmp(argv[0], "unlockf")==0)
nunlock(argv[1]);
return(0);
}
本程序的用法是:
lockf 源文件名

unlockf 源文件名

---- 要 真 正 實 現 信 號 燈 機 制, 我 們 還 必 須 準 備 一 個 簡 單 的script 文 件signal:


if lockf $1
$1 注2
unlockf
else
echo “Error: Another $1 is running.”
fi

---- 這 樣 我 們 在 運 行 文 本 編 輯 器dtpad 時, 輸 入 下 列 命 令:

---- signal dtpad

---- 反 過 來, 對 前 面 提 到 的netscape 程 序, 也 可 以 通 過 編 寫 一 個script 文 件supernet 實 現 多 個 進 程 同 時 運 行:


netscape &
rm /.netscape/lock

---- 注1: 還 有 一 種 方 法, 只 適 用 普 通 用 戶: 在creat 創 建 一 個 新 文 件 時, 即 使 權 限 實 參(permission argument) 不 允 許 寫, 該 文 件 也 被 打 開 用 作 寫。 但creat 在 截 斷 一 個 現 存 文 件 時, 若 無 寫 權 限(write permission), 則 失 敗。 這 樣 就 可 以 只 通 過creat 系 統 調 用 實 現 文 件 信 號 燈 機 制。 但 這 種 做 法 有 一 個 很 明 顯 的 缺 點, 就 是 不 適 用 超 級 用 戶, 因 為 對 超 級 用 戶 沒 有 不 允 許 寫 的 東 西。

---- 注2: 這 不 適 帶& 符 號 的 台 進 程。

---- UNIX 系 統 的 文 件 信 號 燈 機 制

---- 作 為 一 個 多 用 戶、 多 任 務 的 操 作 系 統,UNIX 允 許 某 個 程 序 同 時 運 行 多 個 進 程。 但 有 時 又 由 系 統 資 源 等 因 素 的 制 約, 要 求 一 次 只 能 有 一 個 進 程 在 運 行。 例 如 在Digital UNIX 下 運 行 第 二 個Netscape 進 程 時, 系 統 報 告 如 下 錯 誤 信 息:

---- Netscape has detected a /.netscape/lock file.

---- This may indicate that another user is running Netscape using your /.netscape files.

---- 實 際 上, 第 一 個Netscape 進 程 在 運 行 時, 加 了 一 把 鎖, 禁 止 其 他Netscape 進 程 啟 動。 當 它 結 束 時, 把 鎖 打 開, 其 他 進 程 才 能 進 入。 這 就 是UNIX 的 信 號 燈 機 制。

---- 而Netscape 是 用 文 件 作 為 信 號 燈 的。 在 運 行 前, 先 檢 查 文 件/.netscape/lock 是 否 存 在: 若 存 在, 表 明 鎖 已 掛 上, 新 進 程 不 能 運 行, 只 好 等 待; 若 沒 有, 說 明 鎖 已 打 開, 可 以 運 行 了。

---- 在 掌 握 了 文 件 信 號 燈 的 機 理 , 可 以 自 行 設 計 一 套 萬 能 加 鎖 解 鎖 程 序, 為 每 個 程 序 配 上 各 自 的 鎖 和 鑰 匙。 並 且 使 用 零 字 節 長 度 的 文 件 當 鎖, 減 少 系 統 開 銷。

---- 我 們 用creat 和unlink 兩 個 系 統 調 用 實 現 加 解 鎖 和 檢 測 操 作。 一 個 進 程 運 行 之 前, 先 通 過unlink 檢 測 鎖 文 件 是 否 存 在 注1。unlink 系 統 調 用 從 一 個 目 錄 中 刪 去 一 個 文 件 鏈, 若 成 功 則 返 回0, 表 示 確 有 文 件 存 在; 若 失 敗, 表 明 文 件 不 存 在, 返 回-1。 如 果 還 沒 有 上 鎖, 就 要 用creat 系 統 調 用 創 建 鎖 文 件; 若 鎖 已 掛 上, 雖 然 進 程 並 未 運 行, 但 unlink 無 疑 會 刪 除 鎖 文 件, 所 以 也 要 用creat 來 恢 復。creat 系 統 調 用 創 建 一 個 新 文 件, 函 數 標 題 如 下:


int creat(path, perms) /* create file */
char *path; /* path name */
int perms; /* permission bits */

---- 其 中path 表 示 路 徑 加 文 件 名,perms 是10 位 的 文 件 權 限 描 述 字, 在 加 鎖 程 序 中 取0。 文 件 在 剛 創 建 時, 初 始 長 度 為 零 字 節, 用 它 來 做 鎖 文 件, 可 以 最 大 限 度 地 降 低 系 統 開 銷。

---- 鎖 文 件 規 定 為: 源 文 件 名+“.lok”。 這 樣 一 來, 就 真 正 做 到 了 一 個 程 序 配 一 把 鎖。

---- 下 面 就 列 出 加 鎖 和 解 鎖 的 程 序 清 單。 我 們 用 同 樣 的 程 序 完 成 這 兩 種 完 全 互 斥 的 操 作, 區 別 在 命 令 名 的 不 同。 在C 語 言 源 程 序 裡, 變 量argv[0] 表 示 命 令 名,“lockf” 是 上 鎖,“unlockf” 是 解 鎖。

---- 程 序LOCKF.C 暨UNLOCKF.C 的 源 代 碼


#include < stdio.h >
#include < errno.h >
#include < fcntl.h >
#include < cdatyp.h >
void syserr(msg) /*打印系統調用錯誤信息並中止 */
char *msg;
{
extern int errno, sys_nerr;
extern char *sys_errlist[];

fprintf(stderr, "ERROR: %s (%d", msg, errno);
if (errno >0 && errno< sys_nerr)
fprintf(stderr, "; %s)\n", sys_errlist[errno]);
else
fprintf(stderr, ")\n");
exit(1);
}
short nlock(name) /*上鎖過程 */
char *name;
{ char *path, *lockpath();
int fd, tries;
extern int errno;
short unlink_result;

path=lockpath(name); /*制鎖 */
unlink_result=unlink(path); /*判斷是否已經上鎖 */
fd=creat(path, 0); /*上鎖 */
if (fd==-1 || close(fd)==-1)
syserr("nlock");
if (unlink_result==-1)
return 0xff;
return (0);
}
void nunlock(name) /*解鎖 */
char *name;
{ char *lockpath();
if (unlink(lockpath(name))==-1)
syserr("nunlock");
}
static char *lockpath(name) /*制鎖的過程 */
char *name;
{ static char path[20];
char *strcat();

strcpy(path, name);
return(strcat(path, ".lok"));
}
int main(argc, argv)
int argc;
char *argv[];
{ if (argc!=2)
{ printf("Usage: %s filename\n\r", argv[0]);
return(1);
}
if (strcmp(argv[0], "lockf")==0)
if (!nlock(argv[1]))
{ printf("You can not add the same lock twice!\r\n");
return(2);
}
if (strcmp(argv[0], "unlockf")==0)
nunlock(argv[1]);
return(0);
}
本程序的用法是:
lockf 源文件名

unlockf 源文件名

---- 要 真 正 實 現 信 號 燈 機 制, 我 們 還 必 須 準 備 一 個 簡 單 的script 文 件signal:


if lockf $1
$1 注2
unlockf
else
echo “Error: Another $1 is running.”
fi

---- 這 樣 我 們 在 運 行 文 本 編 輯 器dtpad 時, 輸 入 下 列 命 令:

---- signal dtpad

---- 反 過 來, 對 前 面 提 到 的netscape 程 序, 也 可 以 通 過 編 寫 一 個script 文 件supernet 實 現 多 個 進 程 同 時 運 行:


netscape &
rm /.netscape/lock

---- 注1: 還 有 一 種 方 法, 只 適 用 普 通 用 戶: 在creat 創 建 一 個 新 文 件 時, 即 使 權 限 實 參(permission argument) 不 允 許 寫, 該 文 件 也 被 打 開 用 作 寫。 但creat 在 截 斷 一 個 現 存 文 件 時, 若 無 寫 權 限(write permission), 則 失 敗。 這 樣 就 可 以 只 通 過creat 系 統 調 用 實 現 文 件 信 號 燈 機 制。 但 這 種 做 法 有 一 個 很 明 顯 的 缺 點, 就 是 不 適 用 超 級 用 戶, 因 為 對 超 級 用 戶 沒 有 不 允 許 寫 的 東 西。

---- 注2: 這 不 適 帶& 符 號 的 台 進 程。

---- UNIX 系 統 的 文 件 信 號 燈 機 制

---- 作 為 一 個 多 用 戶、 多 任 務 的 操 作 系 統,UNIX 允 許 某 個 程 序 同 時 運 行 多 個 進 程。 但 有 時 又 由 系 統 資 源 等 因 素 的 制 約, 要 求 一 次 只 能 有 一 個 進 程 在 運 行。 例 如 在Digital UNIX 下 運 行 第 二 個Netscape 進 程 時, 系 統 報 告 如 下 錯 誤 信 息:

---- Netscape has detected a /.netscape/lock file.

---- This may indicate that another user is running Netscape using your /.netscape files.

---- 實 際 上, 第 一 個Netscape 進 程 在 運 行 時, 加 了 一 把 鎖, 禁 止 其 他Netscape 進 程 啟 動。 當 它 結 束 時, 把 鎖 打 開, 其 他 進 程 才 能 進 入。 這 就 是UNIX 的 信 號 燈 機 制。

---- 而Netscape 是 用 文 件 作 (http://www.fanqiang.com)     進入【UNIX論壇


相關文章
 

★  樊強制作 歡迎分享  ★