前前言
别问我为啥Linux没有实验四,我们老师只给了我们实验一、二、三、五、六、七。
我能怎么办啊,我一个强迫症我也难受啊QAQ。
前言
为了帮助同学们完成痛苦的实验课程设计,本作者将其作出的实验结果及代码贴至CSDN中,供同学们学习参考。如有不足或描述不完善之处,敬请各位指出,欢迎各位的斧正!
一、实验目的
- 学习Linux对文件系统的操作方法,掌握编程对文件进行操作的方法;
- 学习Linux下proc文件系统的特殊用途,学会利用其查看系统信息。
二、实验工具与设备
装有Linux系统的计算机
三、实验预备知识
参阅教材中文件系统章节内容
四、实验内容和步骤
一、Linux文件编程
- 从一个文件中读取最后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;
}
- 编译、调试该程序使其能正常工作,运行之。解释这个程序的功能。
二、proc文件系统编程
-
/proc — 一个虚拟文件系统
/proc 文件系统是一种内核和内核模块用来向进程 (process) 发送信息的机制 (所以叫做 /proc)。这个伪文件系统让你可以和内核内部数据结构进行交互,获取有关进程的有用信息,在运行中改变设置。与其他文件系统不同,/proc 存在于内存之中而不是硬盘上。proc 文件系统可以被用于收集有用的关于系统和运行中的内核的信息。 -
下面是一些重要的文件:
/proc/cpuinfo - CPU 的信息 (型号, 家族, 缓存大小等)
/proc/meminfo - 物理内存、交换空间等的信息
/proc/mounts - 已加载的文件系统的列表
/proc/devices - 可用设备的列表
/proc/filesystems - 被支持的文件系统
/proc/modules - 已加载的模块
/proc/version - 内核版本
/proc/cmdline - 系统启动时输入的内核命令行参数
有一些以数字命名的目录,它们是进程目录。系统中当前运行的每一个进程在/proc下都对应一个以进程号为目录名的目录/proc/pid,它们是读取进程信息的接口。 -
通过 /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
以上例子演示了如何修改本机的主机名。
- 使用C语言编写一个主机信息输出程序,使用open、close、read等系统调用读取不同的proc文件,获得主机信息,然后输出出来。
选作:利用write系统调用修改内核信息并验证。
三、使用fcntl函数实现文件锁
- 编写一个文件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;
}
- 编写一个文件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);
}
- 编写一个文件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函数实现多个文件的读写
- 编写如下程序,该程序利用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;
}
其运行截图如下所示: