操作系统实验-系统命令的实现

一、实验目的:

(1)掌握Linux目录操作方法,包括打开目录、关闭目录、读取目录文件

(2)掌握Linux文件属性获取方法,包括三个获取Linux文件属性的函数、文件属性解析相关的宏

(3)掌握POSIX与ANSI C文件I/O操作方法,包括打开文件、关闭文件、创建文件、读写文件、定位文件

二     、实验原理:

(1)cp命令与命令行参数

UNIX/Linux中通过在shell中输入命令名(或可执行文件名)来启动程序,在命令名(可执行文件名)之后可以跟随一系列字符串(通过空格分割), 这些字符串就是命令行参数,例如:

cp [参数] <源文件路径> <目标文件路径>

cp /usr/local/src/main.c /root/main.c(文件到文件复制)

cp /usr/local/src/main.c /root (文件到目录复制)

cp –r /usr/local/src /root(递归复制,用于目录到目录的复制)   

(2)实现文件到文件的拷贝

利用POSIX API在Linux系统上编写应用程序,仿写cp命令的部分功能,将源文件复制到另外一个文件或复制到另外一个目录。源文件路径和目标文件路径通过命令行参数来指定

1、将test1.text复制成test2.txt:

    [test@linux test]$ ./mycp /home/test1.txt /usr/test2.txt

2、将test1.txt复制到/tmp目录中:

    [test@linux test]$ ./mycp /home/test1.txt /tmp(目录)

(3)应用程序命令行参数获取

UNIX/Linux中C语言应用程序的启动函数是main

操作系统通过C启动例程来启动C程序,启动例程会从标准输入获取应用程序的命令行参数,并且将这些参数传递给main函数,例如,main函数定义:

    int main(int argc, char* argv[])

形式参数:

argc :整形,命令行输入参数的个数

argv:字符串数组,以字符串形式存储的命令行参数

(4)打开关闭目录

常用函数:opendir,closedir

头文件:dirent.h

函数定义:

    DIR * opendir(const char * name);

打开参数name指定目录,并使一个目录流与它关联;目录流类似于C库函数中的文件流;失败返回NULL

int closedir(DIR *dir);

关闭指定目录流,释放相关数据结构;成功返回0;失败返回-1。

(5)读取目录文件

常用函数:readdir

头文件:sys/types.h;dirent.h

函数定义:

struct dirent * readdir(DIR * dir);

读取目录流标识的目录文件;目录文件是一系列目录项的列表,每执行一次该函数返回指向当前读取目录项结构的指针;如果到达目录结尾或者有错误发生则返回NULL。

(7)获取文件属性

常用函数:stat,lstat

头文件: sys/stat.h

函数定义:

int stat(const char *path, struct stat *buf);

int lstat(const char *path, struct stat *buf);

两个函数参数相同,功能类似;读取path参数所指定文件的文件属性并将其填充到buf参数所指向的结构体中;对于符号链接文件,lstat返回符号链接文件本身的属性,stat返回符号链接引用文件的文件属性

(8)判断文件类型宏

是否为普通文件: S_ISREG(st_mode)

是否为目录文件 S_ISDIR(st_mode)

是否为字符设备    S_ISCHR(st_mode)

是否为块设备 S_ISBLK(st_mode)

是否为FIFO S_ISFIFO(st_mode)

是否为套接字 S_ISSOCK(st_mode)

是否为符号连接 S_ISLINK(st_mode)

五、实验内容:

利用POSIX API(文件操作也可以使用ANSI C标准I/O库)编程实现cp –r命令,支持将源路径(目录)中的所有文件和子目录,以及子目录中的所有内容,全部拷贝到目标路径(目录)中。

参考代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
//文件拷贝函数
void copy_file(const char *src, const char *dst) {FILE *source, *destination;char ch;source = fopen(src, "rb");destination = fopen(dst, "wb");while ((ch = fgetc(source)) != EOF) {fputc(ch, destination);}fclose(source);fclose(destination);
}
//目录拷贝函数
void copy_directory(const char *src, const char *dst) {DIR *dir;struct dirent *entry;struct stat file_stat;char src_path[256];char dst_path[256];dir = opendir(src);if (dir == NULL) {perror("Error opening source directory");exit(-1);}// 如果目的目录不存在则创建mkdir(dst, 0777);while ((entry = readdir(dir)) != NULL) {// 跳过"."跟".."if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {continue;}// 获取源路径跟目的路径snprintf(src_path, sizeof(src_path), "%s/%s", src, entry->d_name);snprintf(dst_path, sizeof(dst_path), "%s/%s", dst, entry->d_name);if (stat(src_path, &file_stat) == -1) {perror("Error getting file stat");exit(-1);}if (S_ISDIR(file_stat.st_mode)) {// 递归拷贝目录copy_directory(src_path, dst_path);} else {// 拷贝文件copy_file(src_path, dst_path);}}closedir(dir);
}
int main(int argc, char *argv[]) {if (argc != 3) {printf("Usage: %s source destination\n", argv[0]);exit(-1);}copy_directory(argv[1], argv[2]);printf("Copy complete!!!!\n");return 0;
}

本文链接:https://my.lmcjl.com/post/14641.html

展开阅读全文

4 评论

留下您的评论.