读书笔记:第9章 记录上锁 (2)

《UNIX网络编程:卷2》P155-P156:图9-2

fcntl上锁的加1测试

--------------------------------------------

/*
 * lockmain.c
 * 图9-2 文件上锁例子的main函数
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>

#define FILE_MODE	(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
#define MAXLINE 1024
#define SEQFILE	"seqno"

void my_lock(int fd);
void my_unlock(int fd);

int main(int argc, char *argv[])
{
	int			fd;
	long		i, seqno;
	pid_t		pid;
	ssize_t		n;
	char		line[MAXLINE + 1];

	pid = getpid();					// 获取进程ID
	// 打开文件
	if ((fd = open(SEQFILE, O_RDWR, FILE_MODE)) < 0) {
		fprintf(stderr, "open %s error: %s\n",  SEQFILE, strerror(errno));
		exit(1);
	}

	for (i = 0; i < 20; i++) {
		my_lock(fd);									// 锁定文件

		lseek(fd, 0L, SEEK_SET);						//定位到文件开始位置
		if ((n = read(fd, line, MAXLINE)) < 0) {		// 读取一行
			fprintf(stderr, "read error: %s\n", strerror(errno));
			exit(1);
		}
		line[n] = '\0';

		n = sscanf(line, "%ld\n", &seqno);				// 将字符转换成数字
		printf("%s: pid = %d, seq# = %ld\n", argv[0], pid, seqno);

		seqno++;										// 加1

		snprintf(line, sizeof(line), "%ld\n", seqno);	// 将数字写回缓冲区
		lseek(fd, 0L, SEEK_SET);						// 定位到文件开始处
		if (write(fd, line, strlen(line)) < 0) {		// 将缓冲区内容写回文件
			fprintf(stderr, "write error: %s\n", strerror(errno));
			exit(1);
		}

		my_unlock(fd);				// 解锁文件
	}
	exit(0);
}

/*
 * lockfcntl.c
 * P161 图9-3 fcntl上锁
 */
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;

	// 加锁整个文件
	if (fcntl(fd, F_SETLKW, &lock) < 0) {
		fprintf(stderr, "fcntl error: %s\n", strerror(errno));
	}
	return;		// 不做任何事情,直接返回
}

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;

	// 解锁整个文件
	if (fcntl(fd, F_SETLK, &lock) < 0) {
		fprintf(stderr, "fcntl error: %s\n", strerror(errno));
	}
	return;		// 不做任何事情,直接返回
}

--------------------------------------------

创建文件seqno,并写入1。运行程序:

$ ./lockmain & ./lockmain &
[1] 2513
[2] 2514
$ ./lockmain: pid = 2513, seq# = 1
./lockmain: pid = 2513, seq# = 2
./lockmain: pid = 2513, seq# = 3
./lockmain: pid = 2513, seq# = 4
./lockmain: pid = 2513, seq# = 5
./lockmain: pid = 2513, seq# = 6
./lockmain: pid = 2513, seq# = 7
./lockmain: pid = 2513, seq# = 8
./lockmain: pid = 2513, seq# = 9
./lockmain: pid = 2513, seq# = 10
./lockmain: pid = 2513, seq# = 11
./lockmain: pid = 2513, seq# = 12
./lockmain: pid = 2513, seq# = 13
./lockmain: pid = 2513, seq# = 14
./lockmain: pid = 2513, seq# = 15
./lockmain: pid = 2513, seq# = 16
./lockmain: pid = 2513, seq# = 17
./lockmain: pid = 2513, seq# = 18
./lockmain: pid = 2513, seq# = 19
./lockmain: pid = 2513, seq# = 20
./lockmain: pid = 2514, seq# = 21
./lockmain: pid = 2514, seq# = 22
./lockmain: pid = 2514, seq# = 23
./lockmain: pid = 2514, seq# = 24
./lockmain: pid = 2514, seq# = 25
./lockmain: pid = 2514, seq# = 26
./lockmain: pid = 2514, seq# = 27
./lockmain: pid = 2514, seq# = 28
./lockmain: pid = 2514, seq# = 29
./lockmain: pid = 2514, seq# = 30
./lockmain: pid = 2514, seq# = 31
./lockmain: pid = 2514, seq# = 32
./lockmain: pid = 2514, seq# = 33
./lockmain: pid = 2514, seq# = 34
./lockmain: pid = 2514, seq# = 35
./lockmain: pid = 2514, seq# = 36
./lockmain: pid = 2514, seq# = 37
./lockmain: pid = 2514, seq# = 38
./lockmain: pid = 2514, seq# = 39
./lockmain: pid = 2514, seq# = 40

[1]-  完成                  ./lockmain
[2]+  完成                  ./lockmain

该运行结果看上去是正确的,但这不足以告诉我们程序是否正常工作。只循环20次,两个进程中途不进行切换,我们可能永远也发现不了错误。需要更多循环次数的测试。

你可能感兴趣的:(读书笔记,《UNIX网络编程》)