日期:2014-05-16  浏览次数:20893 次

Linux内核设计的艺术-多进程操作文件的综合实例

      进程A是一个写盘进程,目的是往hello1.txt文件中写入str[]中的字符“ABCED”,代码如下:

void FunA();
void main()
{
	...
	FunA();
	...
}

void FunA()
{
	char str1[]="ABCDE";
	int i,j;
	int fd = open("/mnt/user/user1/user2/hello1.txt",O_RDWR,0644);
	for(i=0;i<100000;i++)
	{
		write(fd,str1,strlen(str1));
	}
	close(fd);
}

        进程B是一个写盘进程,目的是往hello2.txt文件中写入str[]中的字符“ABCED”,代码如下:

void FunB();
void main()
{
	...
	FunB();
	...
}

void FunB()
{
	char str1[]="ABCDE";
	int i,j;
	int fd = open("/mnt/user/user1/user2/hello2.txt",O_RDWR,0644);
	for(i=0;i<100000;i++)
	{
		write(fd,str1,strlen(str1));
	}
	close(fd);
}


        进程C是一个读盘进程,目的是从hello3.txt文件中读20000字节到buffer中,代码如下:

void FunC();
void main()
{
	...
	FunC();
	...
}

void FunC()
{
	char buffer[20000];
	int i,j;
	int fd = open("/mnt/user/user1/user2/hello3.txt",O_RDWR,0644);
	read(fd,buffer,sizeof(buffer));
	close(fd);
}
          

        首先进程A开始执行,刚开始的流程是申请缓冲块,往缓冲块写入数据。后来缓冲区中已经没有空闲且不脏的缓冲块,只有空闲且脏的缓冲块。这就意味着,接下来要强行将缓冲区中的数据同步到硬盘,以便在缓冲区中空出更多的空间。请看getblk函数。

        代码路径:fs/buffer.c

#define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)
struct buffer_head * getblk(int dev,int block)
{
	struct buffer_head * tmp, * bh;

repeat:
	if ((bh = get_hash_table(dev,block)))
		return bh;
	tmp = free_list;
	do {
		if (tmp->b_count)
			continue;
		if (!bh || BADNESS(tmp)<BADNESS(bh)) {
			bh = tmp;
			if (!BADNESS(tmp))
				break;
		}
/* and repeat until we find something good */
	} while ((tmp = tmp->b_next_free) != free_list);
	if (!bh) {//bh为空,说明所有的缓冲块b_count都不为0
		sleep_on(&buffer_wait);//等待
		goto repeat;//重新选择
	}
	wait_on_buffer(bh);//找到了b_count为0的缓冲块,如果b_lock为1,则等待
	if (bh->b_count)
		goto repeat;
	while (bh->b_dirt) {//b_dirt为1,说明目前只有空闲且b_dirt为1的缓冲块了
		sync_dev(bh->b_dev);//立即同步
		wait_on_buffer(bh);
		if (bh->b_count)
			goto repeat;
	}
        ...
}
       代码路径:fs/buffer.c

int sync_dev(int dev)
{
	int i;
	struct buffer_head * bh;

	bh = start_buffer;
	for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
		if (bh->b_dev != dev)
			continue;
		wait_on_buffer(bh);
		if (bh->b_dev == dev && bh->b_dirt)//只要设备号符合是脏的,就同步
			ll_rw_block(WRITE,bh);
	}
	...
}
       代码路径:kernel/blk_drv/ll_rw_block.c

void ll_rw_block(int rw, struct buffer_head * bh)
{
	unsigned int major;

	if ((major=MAJOR(bh->b_dev)) >= NR_BLK_DEV ||
	!(blk_dev[major].request_fn)) {
		printk("Trying to re