在 Dfs 中使用 cat cp 等命令时拔掉 U盘 死机问题

网友投稿 599 2022-05-28

一、问题现象

1、使用ls、cp、mv、cat、rm、mkdir、echo命令操作文件未结束之前拔掉U盘,自己写的自动卸载U盘程序会出现死机现象。

二、问题原因

1、每次进行文件操作需要用到互斥锁的,流程:文件系统上锁–文件操作–文件系统解锁。但是上述命令所调用的函数是没有使用互斥锁,操作文件的时候拔掉U盘触发dfs_unmount函数卸载U盘,最终现象为两个线程同时对U盘进行文件操作发生异常。

三、解决方案

1、加上互斥锁即可,系统中已经有现成dfs的互斥锁函数dfs_lock和dfs_unlock,调用即可。在ls、cp、mv、cat、rm、mkdir、echo所调用的函数前进行dfs_lock,调用完成后dfs_unlock就可以解决问题。

2、按照上述进行解决其实使用cat时,拔掉U盘虽然不会死机,但是仍然会有异常发生,具体我会在后面讲到。

修改后的代码,我就不一一截图,直接上修改过的函数,这些函数都是在msh.c。

int cmd_ls(int argc, char **argv) { extern void ls(const char *pathname); dfs_lock(); if (argc == 1) { #ifdef DFS_USING_WORKDIR ls(working_directory); #else ls("/"); #endif } else { ls(argv[1]); } dfs_unlock(); return 0; } int cmd_cp(int argc, char **argv) { void copy(const char *src, const char *dst); dfs_lock(); if (argc != 3) { rt_kprintf("Usage: cp SOURCE DEST\n"); rt_kprintf("Copy SOURCE to DEST.\n"); } else { copy(argv[1], argv[2]); } dfs_unlock(); return 0; } int cmd_mv(int argc, char **argv) { int res = 0; dfs_lock(); if (argc != 3) { rt_kprintf("Usage: mv SOURCE DEST\n"); rt_kprintf("Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n"); } else { int fd; char *dest = RT_NULL; rt_kprintf("%s => %s\n", argv[1], argv[2]); fd = open(argv[2], O_DIRECTORY, 0); if (fd >= 0) { char *src; close(fd); /* it's a directory */ dest = (char *)rt_malloc(DFS_PATH_MAX); if (dest == RT_NULL) { rt_kprintf("out of memory\n"); res = -RT_ENOMEM; goto end; } src = argv[1] + rt_strlen(argv[1]); while (src != argv[1]) { if (*src == '/') break; src --; } rt_snprintf(dest, DFS_PATH_MAX - 1, "%s/%s", argv[2], src); } else { fd = open(argv[2], O_RDONLY, 0); if (fd >= 0) { close(fd); unlink(argv[2]); } dest = argv[2]; } rename(argv[1], dest); if (dest != RT_NULL && dest != argv[2]) rt_free(dest); } end: dfs_unlock(); return res; } int cmd_cat(int argc, char **argv) { int index; extern void cat(const char *filename); dfs_lock(); if (argc == 1) { rt_kprintf("Usage: cat [FILE]...\n"); rt_kprintf("Concatenate FILE(s)\n"); goto end; } for (index = 1; index < argc; index ++) { cat(argv[index]); } end: dfs_unlock(); return 0; } int cmd_rm(int argc, char **argv) { int index, n; char f = 0, r = 0, v = 0; dfs_lock(); if (argc == 1) { rt_kprintf("Usage: rm option(s) FILE...\n"); rt_kprintf("Remove (unlink) the FILE(s).\n"); goto end; } if (argv[1][0] == '-') { for (n = 0; argv[1][n]; n++) { switch (argv[1][n]) { case 'f': f = 1; break; case 'r': r = 1; break; case 'v': v = 1; break; case '-': break; default: rt_kprintf("Error: Bad option: %c\n", argv[1][n]); goto end; } } argc -= 1; argv = argv + 1; } for (index = 1; index < argc; index ++) { struct stat s; if (stat (argv[index], &s) == 0) { if (s.st_mode & S_IFDIR) { if (r == 0) rt_kprintf("cannot remove '%s': Is a directory\n", argv[index]); else directory_delete_for_msh(argv[index], f, v); } else if (s.st_mode & S_IFREG) { if (unlink(argv[index]) != 0) { if (f == 0) rt_kprintf("cannot remove '%s'\n", argv[index]); } else if (v) { rt_kprintf("removed '%s'\n", argv[index]); } } } else if (f == 0) { rt_kprintf("cannot remove '%s': No such file or directory\n", argv[index]); } } end: dfs_unlock(); return 0; } int cmd_mkdir(int argc, char **argv) { dfs_lock(); if (argc == 1) { rt_kprintf("Usage: mkdir [OPTION] DIRECTORY\n"); rt_kprintf("Create the DIRECTORY, if they do not already exist.\n"); } else { mkdir(argv[1], 0); } dfs_unlock(); return 0; } int cmd_df(int argc, char** argv) { dfs_lock(); if (argc != 2) { df("/"); } else { if ((strcmp(argv[1], "--help") == 0) || (strcmp(argv[1], "-h") == 0)) { rt_kprintf("df [path]\n"); } else { df(argv[1]); } } dfs_unlock(); return 0; } int cmd_echo(int argc, char** argv) { dfs_lock(); if (argc == 2) { rt_kprintf("%s\n", argv[1]); } else if (argc == 3) { int fd; fd = open(argv[2], O_RDWR | O_APPEND | O_CREAT, 0); if (fd >= 0) { write (fd, argv[1], strlen(argv[1])); close(fd); } else { rt_kprintf("open file:%s failed!\n", argv[2]); } } else { rt_kprintf("Usage: echo \"string\" [filename]\n"); } dfs_unlock(); return 0; }

四、cat问题现象

1、使用cat命令读取U盘文件并打印读到的数据时突然拔掉U盘,正常会因为读取失败而停止输出,实际上则不断的打印最后读到的一串数据。

五、cat问题原因

1、cat命令实质调用的核心函数是dfs_file_read,这个函数返回一个长度值,如果返回值小于0说明发生错误,但是接收这个返回值的却是一个uint32_t变量,导致出错时无法识别错误,反而识别成读取到长度非常大的数据,所以在不断打印。

在 Dfs 中使用 cat cp 等命令时拔掉 U盘 死机问题

六、cat解决方案

1、将length改成int类型即可

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:LVM卷管理
下一篇:java缓存
相关文章