`
isiqi
  • 浏览: 16499321 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

Linux 下几个文件操作命令的代码实现

阅读更多

转自:http://www.ibm.com/developerworks/cn/linux/l-cn-commands/index.html

本文章中的示例代码是在 CentOS 5.4 64 位环境下运行通过的,在其它 unix 系统上没有测试过。

Linux 操作系统中的命令实际上是编译好的可执行程序,比如说 ls 这个命令,这个文件位于 /bin 目录下面,当我们用 file /bin/ls 命令查看的时候会有以下输出:

 [root@localhost ~]# file /bin/ls 
/bin/ls: ELF 64-bit LSB executable,
AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9,
dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped

这个命令通过调用 stat 系统调用和 /usr/share/file/magic.mgc 文件来决定文件的类型。如上的 /bin/ls 是一个 ELF 格式的动态链接的 64 位的可执行文件。

系统调用是用户程序和操作系统内核之间的接口,我们可以使用操作系统提供的系统调用来请求分配资源和服务。我们可以通过 man 2 章节来查找 Linux 提供的系统调用的具体使用方法。有关文件操作的常见系统调用命令有:open、creat、close、read、write、lseek、opendir、readdir、mkdir、stat 等等。

cp 命令的实现

cp 命令的模拟实现

大家也都知道 cp 这个命令主要的作用就是把一个文件从一个位置复制到另一个位置。比如现在 /root 目录下有一个 test.txt 文件,如果我们用 cp test.txt test2.txt 命令的话,在同一个目录下面就会生成一个同样内容的 test2.txt 文件了。

那么 cp 命令是怎么实现的呢,我们看如下代码:


清单 1. cp 命令实现代码
				
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>

#define BUFFERSIZE 4096
#define COPYMODE 0644

void oops(char *, char *);

main(int argc, char * argv[])
{
int in_fd, out_fd, n_chars;
char buf[BUFFERSIZE];

if ( argc != 3 ){
fprintf( stderr, "usage: %s source destination\n", *argv);
exit(1);
}

if ( (in_fd=open(argv[1], O_RDONLY)) == -1 ){
oops("Cannot open ", argv[1]);
}
if ( (out_fd=creat( argv[2], COPYMODE)) == -1 ){
oops( "Cannot creat", argv[2]);
}

while ( (n_chars = read(in_fd , buf, BUFFERSIZE)) > 0 ){
if ( write( out_fd, buf, n_chars ) != n_chars ){
oops("Write error to ", argv[2]);
}
}
if ( n_chars == -1 ){
oops("Read error from ", argv[1]);
}

if ( close(in_fd) == -1 || close(out_fd) == -1 )
oops("Error closing files","");
}

void oops(char *s1, char *s2)
{
fprintf(stderr,"Error: %s ", s1);
perror(s2);
exit(1);
}

该程序的主要实现思想是:打开一个输入文件,创建一个输出文件,建立一个 BUFFERSIZE 大小的缓冲区;然后在判断输入文件未完的循环中,每次读入多少就向输出文件中写入多少,直到输入文件结束。

cp 命令实现的说明

让我来详细的讲述一下这个程序:

  • 开头四行包含了 4 个头文件,<stdio.h> 文件包含了 fprintf、perror 的函数原型定义;<unistd.h> 文件包含了 read、write 的函数原型定义;<fcntl.h> 文件包含了 open、creat 的函数原型定义、<stdlib.h> 文件包含了 exit 的函数原型定义。这些函数原型有些是系统调用、有些是库函数,通常都可以在 /usr/include 目录中找到这些头文件。
  • 接下来的 2 行以宏定义的方式定义了 2 个常量。BUFFERSIZE 用来表示缓冲区的大小、COPYMODE 用来定义创建文件的权限。
  • 接下来的一行定义了一个函数原型 oops,该函数的具体定义在最后出现,用来输出出错信息到 stderr,也就是标准错误输出的文件流。
  • 接下来主程序开始。首先定义了 2 个文件描述符、一个存放读出字节数的变量 n_chars、和一个 BUFFERSIZE 大小的字符数组用来作为拷贝文件的缓冲区。
  • 接下来判断输入参数的个数是否为 3,也就是程序名 argv[0]、拷贝源文件 argv[1]、目标文件 argv[2]。不为 3 的话就输出错误信息到 stderr,然后退出程序。
  • 接下来的 2 行,用 open 系统调用以 O_RDONLY 只读模式打开拷贝源文件,如果打开失败就输出错误信息并退出。如果想了解文件打开模式的详细内容请使用命令 man 2 open,来查看帮助文档。
  • 接下来的 2 行,用 creat 系统调用以 COPYMODE 的权限建立一个文件,如果建立失败函数的返回值为 -1 的话,就输出错误信息并退出。
  • 接下来的循环是拷贝的主要过程。它从输入文件描述符 in_fd 中,读入 BUFFERSIZE 字节的数据,存放到 buf 字符数组中。在正常读入的情况下,read 函数返回实际读入的字节数,也就是说只要没有异常情况和文件没有读到结尾,那么 n_chars 中存放的就是实际读出的字节的数字。然后 write 函数将从 buf 缓冲区中,读出 n_chars 个字符,写入 in_out 输出文件描述符。由于 write 系统调用返回的是实际写入成功的字节数。所以当读出 N 个字符,又成功写入 N 个字符到输出文件描述符中去的时候,就表示写成功了,否则就报告写入错误。
  • 最后就是用 close 系统调用关闭打开的输入和输出文件描述符。

rm 命令的实现

rm 命令的模拟实现

rm 命令主要是用来删除一个文件。

该命令的实现代码如下:


清单 2. rm 命令代码
				
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

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

int rt;
if(argc != 2){
exit(2);
}else{

if((rt = unlink(argv[1])) != 0){
fprintf(stderr,"error.");
exit(3);
}

}

return 0;

}

其中程序的关键是 unlink 系统调用,unlink 函数原型包含在 <unistd.h> 头文件里面。

用 strace 来跟踪命令

我们从这个程序的创建过程来分析这个程序。

这个命令的模拟程序是怎么写出来的呢?

首先,我们可以在机器上 touch test 建立一个 test 文件,然后调用 strace rm test 命令来查看 rm 命令具体使用了那些系统调用。

通过查看,我们看到主要使用的系统调用如下:

 [root@localhost aa]# strace rm test 
execve("/bin/rm", ["rm", "test"], [/* 24 vars */]) = 0
brk(0) = 0xcc66000
mmap(NULL, 4096, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2aff83ffb000
uname({sys="Linux", node="localhost.localdomain", ...}) = 0
...
...
lstat("test", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
stat("test", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
geteuid() = 0
getegid() = 0
getuid() = 0
getgid() = 0
access("test", W_OK) = 0
unlink("test") = 0
close(1) = 0
exit_group(0) = ?

我们可以看到起主要作用的就是 unlink(“test”) 这个系统调用。

让我们来分析一下这些输出的含义:

  • 首先第一行 execve 系统调用。该系统调用执行参数“/bin/rm”中的程序(以 #! 开头的可执行脚本也可以),后面第一个方括号中表示执行的参数,第二个方括号中表示执行的环境变量。
  • 接下来的 brk 和 mmap 命令,主要是用来给可执行命令分配内存空间。
  • 后面的 lstat 系统调用用来确定文件的 mode 信息,包括文件的类型和权限,文件大小等等。
  • 然后 access 系统调用检查当前用户进程对于 test 文件的写入访问权限。这里返回值为 0 也就是说进程对于 test 文件有写入的权限。
  • 最后调用 unlink 系统调用删除文件。

这里如果我们建立一个目录 test1,然后用 rm test1 去删除这个目录会有什么结果呢?

我们看到有如下输出:

 rm: cannot remove `test1': Is a directory 

这时我们用 strace 命令来追踪一下,发现输出主要是如下不同。

 unlink("test")              = -1 EISDIR (Is a directory) 

这里说明了删除不掉的原因是 unlink 系统调用报错,unlink 它认为 test 是一个目录,不予处理。

那么怎么删除一个目录呢?应该是用 rmdir 系统调用,这样就不会出现上述的问题了。

mkdir 命令的实现

mkdir 命令的模拟实现

再让我们来看看 mkdir 的实现。

完整的代码如下:


清单 3. mkdir 实现代码
				
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>


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

int rt;
if( (rt = mkdir (argv[1],10705)) == -1 ){
fprintf(stderr,"cannot mkdir");
}

return 0;

}

这段代码也比较简单,我这里就不逐行解释了,主要说以下几点:

首先 mkdir 函数是定义于 <sys/stat.h> 和 <sys/types.h> 头文件之中的。

而 fprintf 函数是位于 <stdio.h> 文件之中的。

mkdir 的函数原型如下:

 int mkdir(const char *pathname, mode_t mode); 

mode 声明为 mode_t 类型。

那么 mode_t 数据类型是什么数据类型,应该从哪个文件去查看它的定义呢?

mode_t 数据类型究竟是什么类型

让我们逐步查找一下。

首先从文件 /usr/include/sys/stat.h 中找到 mode_t 类型

/usr/include/sys/stat.h -> typedef __mode_t mode_t;

说明 mode_t 只是对 __mode_t 的一种定义。

然后从 /usr/include/bits/types.h 中找到 __mode_t 类型

/usr/include/bits/types.h -> __STD_TYPE __MODE_T_TYPE __mode_t;

说明 __mode_t 也只是对 __MODE_T_TYPE 的一种定义。

/usr/include/bits/typesizes.h -> #define __MODE_T_TYPE __U32_TYPE

说明 __MODE_T_TYPE 是对 __U32_TYPE 的一种定义。

/usr/include/bits/types.h -> #define __U32_TYPE unsigned int

最后 __U32_TYPE 是一种无符号的整数的定义。

从上述推导可以看出,mode_t 实际上也就是一种无符号整数。

另外如下结构 struct stat 定义中的 st_mode 成员变量也是使用的 mode_t 类型的变量。

从 man 2 stat 中可以找到结构 struct stat 的定义,如下:

  struct stat { 
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};

该结构也是我们在后面的 tac 命令实现中需要用到的结构体。我们需要用到结构体中的 st_size 成员,该成员反映了被读取的文件描述符对应的文件的大小。

tac 命令的实现

tac 命令的模拟实现

tac 命令主要用来以倒序的方式显示一个文本文件的内容,也就是先显示最后一行的内容,最后显示第一行的内容。代码如下:


清单 4. tac 命令实现代码
				
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

#define SIZE 1000001
#define NLINE '\n'


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

char buf[SIZE];
char *p1,*p2,*p3,*p4;
struct stat *fp;
int fd;
fp=(struct stat *)malloc(sizeof(struct stat));

if(argc != 2){
fprintf(stderr,"input error %s \n");
exit(1);
}

if( (fd=open(argv[1],O_RDONLY)) == -1 ){
fprintf(stderr,"open error %s \n",strerror(errno));
exit(1);
}

if(fstat(fd,fp)== -1){
fprintf(stderr,"fstat error %s \n",strerror(errno));
exit(2);
}

if(fp->st_size > (SIZE-1)){
fprintf(stderr,"buffer size is not big enough \n");
exit(3);
}

if(read(fd,buf,fp->st_size) == -1){
fprintf(stderr,"read error.\n");
exit(4);
}

p1=strchr(buf,NLINE);
p2=strrchr(buf,NLINE);
*p2='\0';

do{
p2=strrchr(buf,NLINE);
p4=p2;
p3=p2+sizeof(char);
printf("%s\n",p3);
*p4='\0';
}while(p2 != p1);

if(p2 == p1){
*p2 = '\0';
printf("%s\n",buf);
}

return 0;
}

让我们来运行一下该程序:

程序的运行情况如下,假设编译后的可执行文件名为 emulatetac,有一个文本文件 test.txt。

 # gcc emulatetac.c  -o  emulatetac 
# cat test.txt
1
2
3
a
b
# ./emulatetac test.txt
b
a
3
2
1

可以看出文件内容以倒序方式显示输出了。

tac 命令实现的说明

下面逐行讲解:

  • #include 的头文件,都应该通过 man 2 系统调用命令来查找,这里就不多说了。
  • 下面定义了一个宏常量 SIZE,该常量主要用来表示能够读入最大多少个字节的文件,当文件过大的时候程序就不执行,直接退出。然后定义了宏常量 NLINE 表示换行符'\n'。
  • 接下来主程序体开始了:首先定义一个字符数组 buf,用来把读入文件的每个字节都存在该数组里面。
  • 然后定义了 4 个字符串指针,一个指向结构体 struct stat 的指针 fp,一个文件描述符。
  • 然后为指向结构体的指针 fp 分配存储空间。
  • 接下来判断输入参数是否为 2 个,也就是命令本身和文件名。不是 2 个就直接退出。
  • 然后以只读方式打开输入文件名的文件,也就是 test.txt。打开成功的话,把打开的文件赋值到文件描述符 fd 中,错误的话退出。
  • 然后用 fstat 系统调用把文件描述符 fd 中对应文件的元信息,存放到结构体指针 fp 指向的结构中。
  • 下面判断当文件的大小超过缓冲区数组 buf 的大小 SIZE-1 时,就退出。
  • 下面将把文件 test.txt 中的每个字符存放到数组 buf 中。
  • 下面是程序的核心部分:首先我们找到字符串 buf 中的第一个换行字符存放到 p1 指针里面,然后把最后一个换行字符置为字符串结束符。
  • 接下来我们从后往前查找字符串 buf 中的换行符,直到遇到第一个换行符 p1。同时打印每个找到的换行符'\n'中的下一个字符开始的字符串,也就刚好是一行文本。
  • 最后当从后向前找到第一个换行字符时,打印第一行,程序结束。

df 命令的实现

df 命令的模拟实现

通过 strace 命令查看 df 主要使用了如下的系统调用:open、fstat、read、statfs

我这里实际上是模拟实现的 df --block-size=4096 这个命令,也就是说以 4096 字节为块大小来显示磁盘使用情况。

这里最为关键的是 statfs 这个结构体,该结构体的某些字段被用作 df 命令的输出字段:

        struct statfs { 
long f_type; /* type of filesystem (see below) */
long f_bsize; /* optimal transfer block size */
long f_blocks; /* total data blocks in file system */
long f_bfree; /* free blocks in fs */
long f_bavail; /* free blocks avail to non-superuser */
long f_files; /* total file nodes in file system */
long f_ffree; /* free file nodes in fs */
fsid_t f_fsid; /* file system id */
long f_namelen; /* maximum length of filenames */
};

比如:df --block-size=4096 的输出如下(纵向列出):

 Filesystem  
/dev/sda1
4K-blocks
5077005    f_blocks 字段
Used
145105    f_blocks 字段 -f_bfree 字段
Available
4669841    f_bavail 字段
Use%
4%   (f_blocks-f_bfree)/ f_blocks*100% 来计算磁盘使用率。
Mounted on
/

模拟实现的代码如下:


清单 5. 模拟实现代码
				
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/vfs.h>
#include <math.h>
#define SIZE1 100
#define FN "/etc/mtab"
#define SPACE ' '

int displayapartition(char * pt,char * pt1);

int main(void){

char tmpline[SIZE1];
FILE * fp;
char * pt1;
char * pt2;
char * pt3;


if( (fp = fopen(FN,"r")) == NULL ){
fprintf(stderr,"%s \n",strerror(errno));
exit(5);
}

while( fgets(tmpline, SIZE1, fp) != NULL ){
pt1=strchr(tmpline, SPACE);
pt2=pt1+sizeof(char);
*pt1='\0';
pt3=strchr(pt2,SPACE);
*pt3='\0';
if(strstr(tmpline,"/dev") != NULL ){
displayapartition(tmpline,pt2);
}
}
return 0;
}

int displayapartition(char * pt,char * pt1){

struct statfs buf;
statfs(pt1,&buf);
int usage;
usage=ceil((buf.f_blocks-buf.f_bfree)*100/buf.f_blocks);

printf("%s ",pt);
printf("%ld ",buf.f_blocks);
printf("%ld ",buf.f_blocks-buf.f_bfree);
printf("%ld ",buf.f_bavail);
printf("%d%% ",usage);
printf("%s ",pt1);
printf("\n");

return 0;
}

df 命令实现的说明

下面解释一下这个程序:

  • 首先,该程序定义了一个函数 displayapartition, 这里先定义它的函数原型。
  • 然后我们从主程序说起:首先定义了一个 char tmpline[SIZE1] 数组,该数组用来存放从宏定义常量 FN 代表的文件中,打开后存入文件的每行记录。
  • 接着定义了一个文件流指针和 3 个字符串指针。
  • 接下来打开文件 FN并把结果赋值给文件流变量 fp, 如果打开失败就退出。
  • 下面从打开的文件流中读出 SIZE1 个字符到临时数组 tmpline。比如读出一行数据为:/dev/sda1 / ext3 rw 0 0  将把 /dev/sda1 放入数组 tmpline,把加载点 / 放入指针 pt2,同时判断字符串 tmpline 是否包含 /dev 字符串,这样来判断是否是一个磁盘文件,如果是的话就调用子函数 displayapartition,不是则返回。
  • 子函数 displayapartition 是做什么的呢?该函数接受 2 个参数,一个是行 /dev/sda1 / ext3 rw 0 0 中的第一列比如:/dev/sda1 也就是实际磁盘作为 pt 指针,一个是行中的第二列比如:/ 也就是挂载点作为 pt1 指针。然后子函数通过 pt1 指针,读取挂载上的文件系统信息到 buf 数据结构里面。
  • 根据开头介绍过的 statfs 结构体,buf.f_blocks 表示打开的文件系统的总数据块,buf.f_blocks-buf.f_bfree 表示已经使用的数据块,buf.f_bavail 表示非超级用户可用的剩余数据块,磁盘使用率就是前面列出过的计算表达式:(f_blocks- f_bfree)/ f_blocks*100%。通过子函数就可以打印出 df 需要显示的所有信息到标准输出了。

小结

本文依次讲述了 cp、rm、mkdir、tac、df 命令的主要功能实现代码,当然每个命令还有很多参数,我这个模拟实现代码甚至连主要功能的很多细节都没有实现,比如 df 命令的输出头我没有打印出来,这牵涉到打印头和输出格式化等很多细节。所以,从这里我们就可以推断出,真实的源代码肯定是考虑得非常全面、严谨和健壮的。我这里只是抛砖引玉,希望能给爱好 Linux 的朋友们提供一种理解 Linux 系统的思路。


下载

描述 名字 大小 下载方法
样例代码 code.zip 3KB HTTP

关于下载方法的信息


参考资料

学习

讨论

分享到:
评论

相关推荐

    Linux下C语言实现文件拷贝

    通过上述分析,我们可以看到这段代码实现了从一个文件读取数据并写入另一个文件的基本过程。虽然这个例子非常简单,但它涵盖了文件操作的基础知识。在实际开发中,可能还需要考虑更多的异常情况处理和优化措施,例如...

    自己实现linux下ls

    代码实现中,还需要注意以下几点: 1. 错误处理:对于可能出现的错误,如打开目录失败、读取目录条目失败等,需要提供适当的错误提示。 2. 输出格式:`ls`命令通常会将文件名和目录名排列得整齐有序,我们也可以考虑...

    linux ls命令 源代码

    Linux系统中的`ls`命令是日常操作中最常用的命令之一,用于列出目录中的文件和子目录。这个命令在Unix-like系统中具有悠久的历史,是任何Linux用户必须掌握的基础工具。源代码的学习可以帮助我们深入理解它的运作...

    Linux操作系统下常见文件类型分析

    压缩和打包文件是指使用某种压缩算法或打包工具将多个文件或文件夹压缩或打包到一个文件中的文件。常见的压缩和打包文件包括: * .bz2 文件:使用 bzip2 命令压缩的文件,可以使用 bzip2 -d filename 解包。 * .gz ...

    linux文件系统详解及常用命令

    2. 单一目录树:Linux 文件系统只有一个目录树,无论操作系统管理几个磁盘分区。 3. 多用户支持:Linux 文件系统支持多用户,每个用户都有自己的主目录。 Linux 文件系统的主要目录: 1. /bin:二进制可执行命令 2...

    操作系统--文件系统实验源代码

    10. **可执行文件**:这部分可能包含实现上述功能的C语言程序,通过编译和运行这些源代码,你可以直观地理解文件系统操作的底层实现。 这个实验不仅有助于理解文件系统的工作原理,还有助于提升Linux操作技能,对...

    .Iinux系统的二级文件系统(QT实现了简单界面,包含原始控制台源码)操作 系统- Linux

    为linux系统设计一个简单的二级文件系统。要求做到以下几点: (1)可以实现下列几条命令(至少4条); login 用户登陆 dir 列文件目录 create 创建文件 delete 删除文件 open 打开文件 close 关闭文件 read 读文件...

    linux file 命令的源代码

    源代码通常包含以下几个关键部分: 1. **主程序**:`file`命令的入口点通常在名为`main.c`或`file.c`的文件中。这个文件定义了命令行参数解析、文件处理逻辑和整体流程控制。 2. **数据结构**:`file`命令需要解析...

    linux下用C实现简单的命令解释器

    通过分析这些源代码,我们可以深入理解Linux进程管理、文件I/O和命令解释器的工作原理,这对于任何想要深入学习Linux系统编程的人来说都是宝贵的实践经验。同时,这个项目也是对C语言编程技巧和Linux系统知识的综合...

    linux下的文件过滤驱动

    在Linux操作系统中,文件过滤驱动是一种特殊的内核模块,它允许对文件系统操作进行拦截、修改或监控。这种驱动程序通常被用在安全软件、审计系统或者需要对文件访问进行特殊控制的应用中。本文将详细讲解Linux文件...

    文件系统实验代码,操作系统

    在这个实验中,你可能会接触到以下几个核心概念: 1. **文件的创建和删除**:文件的创建涉及在磁盘上分配空间并记录文件元信息,如文件名、大小、创建时间等。删除文件时,不仅要释放空间,还要更新文件系统的数据...

    c++实现linux下ls命令

    Linux文件系统是一个树型结构,以/为根目录,包括普通文件、目录文件、链接文件、设备文件、管道文件等几种类型。目录文件的内容是一个列表,包括它所包含的所有文件和子目录的名称。 为了实现ls命令,需要使用到...

    linux 查找文件命令.pdf

    本文将基于提供的文档信息,详细介绍几个常用的Linux文件查找命令:`locate`、`find`以及其他的辅助命令如`more`和`less`。通过这些命令的学习,可以帮助用户更加高效地管理文件和目录。 #### locate `locate`命令...

    linux文件命令linux

    本文将详细介绍几个常见的Linux文件命令,包括`file`、`mkdir`和`grep`,以及它们的用法、选项和实际应用场景。 首先,我们来看`file`命令。`file`的主要功能是对文件进行检测并识别其类型,这有助于用户理解文件的...

    linux下查看文件

    在Linux下,查看文件通常涉及到以下几个步骤: 1. 打开文件:使用`open()`函数打开文件,这个函数会返回一个文件描述符,后续的读写操作都将通过这个描述符进行。例如: ```c int fd = open("file.txt", O_RDONLY...

    操作系统课程设计文件管理二级文件系统.doc

    在这个设计中,我们需要实现几个核心功能: 1. 用户登录(Login):设计一个登录系统,用户需输入正确的用户名和密码才能访问文件系统。在这里,预设的用户名为"admin",密码也为"admin"。登录验证成功后,用户才能...

    linux.pdf 基本所有的命令大全

    Linux系统下提供了丰富的命令来操作文件和目录。例如: - 查看当前工作目录:使用`pwd`命令; - 切换工作目录:使用`cd`命令,后接路径; - 列出目录内容:使用`ls`命令,并可以配合选项展示更多信息; - 统计目录...

    linux ps命令源码

    在Linux操作系统中,`ps`命令是一个非常基础且重要的工具,用于查看系统当前进程的状态。它的功能强大,能够提供各种不同的输出格式,帮助系统管理员监控和管理系统的运行情况。源码分析可以帮助我们深入理解`ps`...

    LINUX操作系统文件系统设计实验代码

    为LINUX系统设计一个简单的二级文件系统,要求: (1)可以实现以下几条命令 login 用户登录 dir 列文件目录 ...... (2)列文件目录是要列出文件名,物理地址,保护码和文件长度。 (3)源文件可以进行读写保护。

Global site tag (gtag.js) - Google Analytics