Linux第五次试验:Linux文件系统管理编程

前前言

别问我为啥Linux没有实验四,我们老师只给了我们实验一、二、三、五、六、七。
我能怎么办啊,我一个强迫症我也难受啊QAQ。

前言

为了帮助同学们完成痛苦的实验课程设计,本作者将其作出的实验结果及代码贴至CSDN中,供同学们学习参考。如有不足或描述不完善之处,敬请各位指出,欢迎各位的斧正!

一、实验目的

  1. 学习Linux对文件系统的操作方法,掌握编程对文件进行操作的方法;
  2. 学习Linux下proc文件系统的特殊用途,学会利用其查看系统信息。

二、实验工具与设备

装有Linux系统的计算机

三、实验预备知识

参阅教材中文件系统章节内容

四、实验内容和步骤

一、Linux文件编程

  1. 从一个文件中读取最后10KB数据并复制到另一个文件,注意观察缓存大小OFFSET对运行效率的影响
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#define BUFFER_SIZE 1024
#define SRC_FILE_NAME "src_file"
#define DEST_FILE_NAME "dest_file"
#define OFFSET 10240
int main()
{
	int src_file,dest_file;
	unsigned char buff[BUFFER_SIZE];
	int real_read_len;
	src_file = open(SRC_FILE_NAME,O_RDONLY);
	dest_file = open(DEST_FILE_NAME,O_WRONLY|O_CREAT,644);
	if(src_file < 0 || dest_file < 0)
	{
		printf("Open file error!\n");
		exit(1);
	}
	lseek(src_file,-OFFSET,SEEK_END);
	while((real_read_len =  read(src_file,buff,sizeof(buff))) > 0)
	{
		write(dest_file,buff,real_read_len);
	}
	close(dest_file);
	close(src_file);
	return 0;
}
  1. 编译、调试该程序使其能正常工作,运行之。解释这个程序的功能。

二、proc文件系统编程

  1. /proc — 一个虚拟文件系统
    /proc 文件系统是一种内核和内核模块用来向进程 (process) 发送信息的机制 (所以叫做 /proc)。这个伪文件系统让你可以和内核内部数据结构进行交互,获取有关进程的有用信息,在运行中改变设置。与其他文件系统不同,/proc 存在于内存之中而不是硬盘上。proc 文件系统可以被用于收集有用的关于系统和运行中的内核的信息。

  2. 下面是一些重要的文件:
    /proc/cpuinfo - CPU 的信息 (型号, 家族, 缓存大小等)
    /proc/meminfo - 物理内存、交换空间等的信息
    /proc/mounts - 已加载的文件系统的列表
    /proc/devices - 可用设备的列表
    /proc/filesystems - 被支持的文件系统
    /proc/modules - 已加载的模块
    /proc/version - 内核版本
    /proc/cmdline - 系统启动时输入的内核命令行参数
    有一些以数字命名的目录,它们是进程目录。系统中当前运行的每一个进程在/proc下都对应一个以进程号为目录名的目录/proc/pid,它们是读取进程信息的接口。

  3. 通过 /proc 中可读写的文件提供了对内核的交互机制。写这些文件可以改变内核的状态。大部分 /proc 的文件是只读的,/proc/sys 目录存放所有可读写的文件的目录,可以被用于改变内核行为, /proc/sys/kernel 目录包含反通用内核行为的信息。
    例如:

$ hostname
	machinename.domainname.com 
$ cat /proc/sys/kernel/hostname
	machinename 
$ echo "new-machinename"  >  /proc/sys/kernel/hostname 
$ hostname
	new-machinename.domainname.com

以上例子演示了如何修改本机的主机名。

  1. 使用C语言编写一个主机信息输出程序,使用open、close、read等系统调用读取不同的proc文件,获得主机信息,然后输出出来。
    选作:利用write系统调用修改内核信息并验证。

三、使用fcntl函数实现文件锁

  1. 编写一个文件lock_set.c,该程序利用fcntl函数实现了一个lock_set函数,该函数实现文件锁功能,F_RDLCK为读锁,F_WRLCK为写锁,F_UNLCK为解锁。
int lock_set(int fd,int type)
{
	struct flock old_lock,lock;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;
	lock.l_type = type;
	lock.l_pid = -1;
	fcntl(fd,F_GETLK,&lock);
	if(lock.l_type != F_UNLCK)
	{
		if(lock.l_type == F_RDLCK)
			printf("Read lock already set by %d\n",lock.l_pid);
		else if(lock.l_type == F_WRLCK)
			printf("Write lock already set by %d\n",lock.l_pid);
	}
	lock.l_type = type;
	if((fcntl(fd,F_SETLKW,&lock)) < 0)
	{
		printf("Lock failed:type = %d\n",lock.l_type);
		return 1;
	}
	switch(lock.l_type)
	{
		case F_RDLCK:
			printf("Read lock set by %d\n",getpid());
			break;
		case F_WRLCK:
			printf("Write lock set by %d\n",getpid());
			break;
		case F_UNLCK:
			printf("Release lock set by %d\n",getpid());
			return 1;
			break;
		default:
			break;
	}
	return 0;
}
  1. 编写一个文件read_lock.c,该文件调用lock_set函数对文件hello上读锁。
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include "lock_set.c"
int main(void)
{
	int fd;
	fd = open("hello",O_RDWR|O_CREAT,0644);
	if(fd<0)
	{
		printf("Open file error.\n");
		exit(1);
	}
	lock_set(fd,F_RDLCK);
	getchar();
	lock_set(fd,F_UNLCK);
	getchar();
	close(fd);
	exit(0);
}
  1. 编写一个文件write_lock.c,该文件调用lock_set函数对文件hello上写锁。
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include "lock_set.c"
int main(void)
{
	int fd;
	fd = open("hello",O_RDWR|O_CREAT,0644);
	if(fd<0)
	{
		printf("Open file error.\n");
		exit(1);
	}
	lock_set(fd,F_WRLCK);
	getchar();
	lock_set(fd,F_UNLCK);
	getchar();
	close(fd);
	exit(0);
}

四、使用select函数实现多个文件的读写

  1. 编写如下程序,该程序利用select函数同时对文件in1、in2和标准输入文件进行读操作。当从标准输入文件读到字母q或Q时退出。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#define  MAX_BUFFER_SIZE  	1024
#define  IN_FILES  		3
#define	 TIME_DELAY		60
#define  MAX(a,b)		((a>b)?(a):(b))
int main(void)
{
	int fds[IN_FILES];
	char buf[MAX_BUFFER_SIZE];
	int i,res,real_read,maxfd;
	struct timeval tv;
	fd_set inset, tmp_inset;			// fd set
	fds[0] = 0;
	if((fds[1] = open("in1", O_RDONLY|O_NONBLOCK)) < 0)
	{
		printf("Open in1 error.\n");
		return 1;
	}
	if((fds[2] = open("in2", O_RDONLY|O_NONBLOCK)) < 0)
	{
		printf("Open in2 error.\n");
		return 1;
	}
	
	maxfd = MAX(fds[1],fds[2]);
	FD_ZERO(&inset);				// clear fd set
	for(i=0;i<IN_FILES;i++)
		FD_SET(fds[i],&inset);			// add fds into fd set
//	FD_SET(0,&inset);
	tv.tv_sec = TIME_DELAY;
	tv.tv_usec = 0;
	while(FD_ISSET(fds[0], &inset) || FD_ISSET(fds[1], &inset) || FD_ISSET(fds[2], &inset)) // in the fd set or not
	{
		tmp_inset = inset;			// backup the fd set
		res = select(maxfd + 1, &tmp_inset, NULL, NULL, &tv); // read fd set
		switch(res)
		{
			case -1:
				{
					printf("Select error\n");
					return 1;
				}
				break;
			case 0:
				{
					printf("Time out\n");
					return 1;
				}
				break;
			default:
				for(i=0;i<IN_FILES;i++)
				{
					if(FD_ISSET(fds[i], &tmp_inset))
					{
						memset(buf, 0, MAX_BUFFER_SIZE);
						real_read = read(fds[i], buf, MAX_BUFFER_SIZE);
						if(real_read < 0)
						{
							if(errno != EAGAIN)
								return 1;
						}
						else if(!real_read)
						{
							close(fds[i]);
							FD_CLR(fds[i], &inset);
						}
						else
						{
							if(i == 0)	// input file
							{
								if((buf[0] == 'q') || (buf[0] == 'Q'))
									return 1;
							}
							else
							{
								buf[real_read] = '\0';
								printf("%s",buf);
							}
						}
					}
				}
				break;
		}
	}
	return 0;
}

四、实验代码及步骤截图

5-1.c:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#define BUFFER_SIZE 1024
#define SRC_FILE_NAME "src_file"
#define DEST_FILE_NAME "dest_file"
#define OFFSET 10240
int main()
{
	int src_file,dest_file;
	unsigned char buff[BUFFER_SIZE];
	int real_read_len;
	src_file = open(SRC_FILE_NAME,O_RDONLY);
	dest_file = open(DEST_FILE_NAME,O_WRONLY|O_CREAT,644);
	if(src_file < 0 || dest_file < 0)
	{
		printf("Open file error!\n");
		exit(1);
	}
	lseek(src_file,-OFFSET,SEEK_END);
	while((real_read_len =  read(src_file,buff,sizeof(buff))) > 0)
	{
		write(dest_file,buff,real_read_len);
	}
	close(dest_file);
	close(src_file);
	return 0;
}

运行截图如下所示:
在这里插入图片描述
在这里插入图片描述
本程序的功能:此程序读取src_file的末10KB文件,并复制到dest_file中。

Lock_set.c:

int lock_set(int fd,int type)
{
	struct flock old_lock,lock;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;
	lock.l_type = type;
	lock.l_pid = -1;
	fcntl(fd,F_GETLK,&lock);
	if(lock.l_type != F_UNLCK)
	{
		if(lock.l_type == F_RDLCK)
			printf("Read lock already set by %d\n",lock.l_pid);
		else if(lock.l_type == F_WRLCK)
			printf("Write lock already set by %d\n",lock.l_pid);
	}
	lock.l_type = type;
	if((fcntl(fd,F_SETLKW,&lock)) < 0)
	{
		printf("Lock failed:type = %d\n",lock.l_type);
		return 1;
	}
	switch(lock.l_type)
	{
		case F_RDLCK:
			printf("Read lock set by %d\n",getpid());
			break;
		case F_WRLCK:
			printf("Write lock set by %d\n",getpid());
			break;
		case F_UNLCK:
			printf("Release lock set by %d\n",getpid());
			return 1;
			break;
		default:
			break;
	}
	return 0;
}

Read_lock.c:

#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include "lock_set.c"
int main(void)
{
	int fd;
	fd = open("hello",O_RDWR|O_CREAT,0644);
	if(fd<0)
	{
		printf("Open file error.\n");
		exit(1);
	}
	lock_set(fd,F_RDLCK);
	getchar();
	lock_set(fd,F_UNLCK);
	getchar();
	close(fd);
	exit(0);
}

Write_lock.c:

#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include "lock_set.c"
int main(void)
{
	int fd;
	fd = open("hello",O_RDWR|O_CREAT,0644);
	if(fd<0)
	{
		printf("Open file error.\n");
		exit(1);
	}
	lock_set(fd,F_WRLCK);
	getchar();
	lock_set(fd,F_UNLCK);
	getchar();
	close(fd);
	exit(0);
}

运行截图如下所示:
在这里插入图片描述
在这里插入图片描述

5-2.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#define  MAX_BUFFER_SIZE  	1024
#define  IN_FILES  		3
#define	 TIME_DELAY		60
#define  MAX(a,b)		((a>b)?(a):(b))
int main(void)
{
	int fds[IN_FILES];
	char buf[MAX_BUFFER_SIZE];
	int i,res,real_read,maxfd;
	struct timeval tv;
	fd_set inset, tmp_inset;			// fd set
	fds[0] = 0;
	if((fds[1] = open("in1", O_RDONLY|O_NONBLOCK)) < 0)
	{
		printf("Open in1 error.\n");
		return 1;
	}
	if((fds[2] = open("in2", O_RDONLY|O_NONBLOCK)) < 0)
	{
		printf("Open in2 error.\n");
		return 1;
	}
	
	maxfd = MAX(fds[1],fds[2]);
	FD_ZERO(&inset);				// clear fd set
	for(i=0;i<IN_FILES;i++)
		FD_SET(fds[i],&inset);			// add fds into fd set
//	FD_SET(0,&inset);
	tv.tv_sec = TIME_DELAY;
	tv.tv_usec = 0;
	while(FD_ISSET(fds[0], &inset) || FD_ISSET(fds[1], &inset) || FD_ISSET(fds[2], &inset)) // in the fd set or not
	{
		tmp_inset = inset;			// backup the fd set
		res = select(maxfd + 1, &tmp_inset, NULL, NULL, &tv); // read fd set
		switch(res)
		{
			case -1:
				{
					printf("Select error\n");
					return 1;
				}
				break;
			case 0:
				{
					printf("Time out\n");
					return 1;
				}
				break;
			default:
				for(i=0;i<IN_FILES;i++)
				{
					if(FD_ISSET(fds[i], &tmp_inset))
					{
						memset(buf, 0, MAX_BUFFER_SIZE);
						real_read = read(fds[i], buf, MAX_BUFFER_SIZE);
						if(real_read < 0)
						{
							if(errno != EAGAIN)
								return 1;
						}
						else if(!real_read)
						{
							close(fds[i]);
							FD_CLR(fds[i], &inset);
						}
						else
						{
							if(i == 0)	// input file
							{
								if((buf[0] == 'q') || (buf[0] == 'Q'))
									return 1;
							}
							else
							{
								buf[real_read] = '\0';
								printf("%s",buf);
							}
						}
					}
				}
				break;
		}
	}
	return 0;
}

其运行截图如下所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Knight_V_Schumacher

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值