同期——記録ロック


レコード・ロックは、親関係または親関係のないプロセス間でファイルの読み取りと書き込みを共有するために使用できる、読み書きロックの拡張タイプです.ロックされたファイルはその記述子によってアクセスされ、ロック操作を実行する関数はfcntlである.このタイプのロックは、通常、カーネル内で維持され、その所有者は、異なるプロセス間のロックに使用できる所有者のプロセスIDによって識別される.
Posixレコードロックは、ファイル全体を指定するための特殊なバイト範囲を定義し、その開始オフセットは0であり、長さも0である.粒度は、ロックできるオブジェクトのサイズをマークするために使用され、Posixレコードロックでは粒度は1 byteである.
#include <fcntl.h>
struct flock{
       short l_type; /* F_RDLCK, F_WRLCK, F_UNLCK */
       short l_whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
       off_t l_start; 
       off_t l_end; /* #bytes, 0 means until e-o-f */
       pid_t l_pid; /* PID returned by F_GETLK */
};
int fcntl(int fd, int cmd, .../*struct flock *arg */); //         cmd,  -1
       
cmdパラメータには3つの値があります:F_SETLK, F_GETLK, F_SETLKW(wait)
F_SETLK:typeを取得またはロック解除
F_SETLKW:とF_SETLK同様、ロックが許可されるまでブロックされます
F_GETLK:argが指すロックをチェックして、既存のロックがあるかどうかを確認すると、呼び出しプロセスに新しいロックを付与するのを妨げることになります.存在しなければargが指すflock構造のtypeメンバーはF_に置かれるUNLCK;それ以外の場合は、ロックが存在するプロセスIDを含むロックが存在する情報を返します.
呼び出しプロセスがすでに持っている同じバイト範囲のロックは、新しいロックの取得を妨げることはありません.同じプロセス内で実行された後に実行される取得ロックコマンドは、先に実行されたコマンドを上書きします.
fcntlレコードロックは、読み取りにも書き込みにも使用できます.1つのファイルの任意のバイトに対して、最大1つのタイプのロックしか存在しません.また、1つの所与のバイトに複数の読み出しロックがあってもよいが、1つの書き込みロックしかない.もちろん、記述子が開いて読んでいない場合、読み出しロックが要求され、エラーが発生します.同様に、記述子が開いて書かれていない場合、書き込みロックを要求するエラーも発生します.ファイルを開いている特定のプロセスでは、ファイルのすべての記述子を閉じたり、それ自体が終了したりすると、ファイルに関連付けられたすべてのロックが削除されます.ロックはforkでサブプロセスから継承できません.
#include	"unpipc.h"

void my_lock(int fd)
{
	struct flock	lock;

	lock.l_type = F_WRLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;				/* write lock entire file */

	Fcntl(fd, F_SETLKW, &lock);
}

void my_unlock(int fd)
{
	struct flock	lock;

	lock.l_type = F_UNLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;				/* unlock entire file */

	Fcntl(fd, F_SETLK, &lock);
}

Posixレコードロックは勧告ロックと呼ばれ,カーネルは各プロセスでロックされたすべてのファイルの正しい情報を維持しているが,十分な権限を持つ他のプロセスの乱れを防止することはできない.Posixレコードロックはコラボレーションプロセスに十分です
ロックを記録する一般的な用途は、プログラムがいつでも1つのコピーだけで実行され、デーモンプロセスでよく使用されることを保証することです.
#include	"unpipc.h"

#define	PATH_PIDFILE	"pidfile"

int
main(int argc, char **argv)
{
	int		pidfd;
	char	line[MAXLINE];

		/* 4open the PID file, create if nonexistent */
	pidfd = Open(PATH_PIDFILE, O_RDWR | O_CREAT, FILE_MODE);

		/* 4try to write lock the entire file */
	if (write_lock(pidfd, 0, SEEK_SET, 0) < 0) {
		if (errno == EACCES || errno == EAGAIN)
			err_quit("unable to lock %s, is %s already running?",
					 PATH_PIDFILE, argv[0]);
		else
			err_sys("unable to lock %s", PATH_PIDFILE);
	}

		/* 4write my PID, leave file open to hold the write lock */
	snprintf(line, sizeof(line), "%ld
", (long) getpid()); Ftruncate(pidfd, 0); Write(pidfd, line, strlen(line)); /* then do whatever the daemon does ... */ pause(); }