Linux文件操作(三)

2023-10-27

mkdir和rmdir
我们可以使用mkdir和rmdir来创建和移除目录.
其语法如下:
#include <sys/stat.h>
int mkdir(const char *path, mode_t mode);
mkdir系统调用可以用来创建目录,而这是与mkdir程序相等同的.mkdir以path为名字创建一个新的目录.目录的权限是由参数mode来指定的,而这也与open系统调用中的O_CREAT的选项是一样的,而且这也是要受到umask的影响.
rmdir语法如下:
#include <unistd.h>
int rmdir(const char *path);
rmdir系统调用将会删除目录,但是只有这个目录为空时才会操作成功.rmdir程序使用系统调用来完成他的工作.
chdir和getcwd

程序在目录中浏览的方式与用户在文件系统中浏览的方式相类似。与我们在Shell中使用cd命令切换目录相类似,一个程序也可以使用chdir系统调用。

#include <unistd.h>
int chdir(const char *path);

程序可以通过调用getcwd函数来确定当前的工作目录。

#include <unistd.h>
char *getcwd(char *buf, size_t size);

getcwd函数将当前目录的名字写入指定的缓冲区buf中。如果目录的名字超过了作为参数传递的缓冲区的尺寸size(ERANGE错误),则会返回null。如果成功则会返回buf。

浏览目录

Linux 系统上的一个通常问题就是目录浏览,也就是说,决定文件所在的特定的目录。在Shell程序中,这是很简单的,只需要Shell扩展通配符表达式即可。在 过去,不同的Unix变种允许程序员访问底层的文件系统结构。我们仍然可以像打开普通文件一样打开一个目录,然后直接读取目录实体,但是不同的文件系统结 构以及实现使得这种方法不可移植。现在已经开发了一个标准的库函数套件,使得目录浏览更为简单。

目录函数在头文件dirent.h中进行 了声明。他们使用一个结构,DIR,作为目录操作的基础。指向这个结构的指针,称之为一个目录流(DIR *),其作用与通常文件操作的文件流(FILE *)相类似。在dirent结构中返回的目录实体本身也在dirent.h中进行声明,因而我们绝不应直接修改DIR结构的域。

我们将会了解下面这些函数:

opendir,closedir
readdir
telldir
seekdir

opendir

opendir函数会打开一个目录,并且建立一个目录流。如果成功,他会返回一个指向用来读取目录实体的DIR结构。

#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);

如果失败,则会返回一个null指针。注意,一个目录流使用低层的文件描述符来访问目录本身,所以如果打开太多文件时opendir会失败。

readdir

readdir 函数会返回一个指向目录流dirp中下一个目录实体详细信息的结构。成功调用readdir函数会返回下一个目录实体。如果发生错误,或是到达目录结尾 处,readdir会返回NULL。POSIX系统在返回NULL时并不会改变errno的值,只有当发生错误时才会改变errno的值。

#include <sys/types.h>
#include <dirent.h>
struct dirent *readdir(DIR *dirp);

注意,如果同时有其他的进程正在创建或是删除目录中的文件,readdir浏览并不会列出目录中的所有文件。

dirent结构包含目录实体的详细信息,包括下面一些实体:

ino_t d_ino:文件的i节点
char d_name[]:文件名字

要确定目录中一个文件的更为详细的信息,我们需要调用stat函数,我们在前面已经讨论了这个函数。

telldir

telldir函数返回一个目录流中记录当前位置的值。然后我们可以调用seekdir将目录浏览设置为当前位置。

#include <sys/types.h>
#include <dirent.h>
long int telldir(DIR *dirp);

seekdir

seekdir函数设置dirp指定的目录流的目录实体指针。用来设置位置的loc值应是由前面的telldir函数得到的。

#include <sys/types.h>
#include <dirent.h>
void seekdir(DIR *dirp, long int loc);

closedir

closedir函数关闭一个目录流,并且释放与其相关的资源。如果成功则会返回0,否则返回一个错误。

#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);

在下一个程序printdir.c中,我们集中了各种文件操作函数来创建一个简单的目录列表。目录中的每一个文件列在其所在行。每一个子目录在其名字后跟一个短划线,而其中的文件空余四个空格显示。

程序可以切换进入子目录,这样他所查找的文件就可以有可用的名字,也就是说,他们可以直接传递给opendir。这个程序在过深的嵌套目录中会失败,因为在打开的目录流数量上存在限制。

当然,我们可以通过命令行参数来指定开始点,从而使得程序变得更为通用。我们可以查看ls或是find的Linux源代码来查看更为通用的目录方法。

一个目录浏览程序

1 我们相关的头文件,以及打印当前目录的printdir函数开始。对于子目录,可以使用depth参数来进行重用。

#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
void printdir(char *dir, int depth)
{
    DIR *dp;
    struct dirent *entry;
    struct stat statbuf;
    if((dp = opendir(dir)) == NULL) {
        fprintf(stderr,”cannot open directory: %s/n”, dir);
        return;
    }
    chdir(dir);
    while((entry = readdir(dp)) != NULL) {
        lstat(entry->d_name,&statbuf);
        if(S_ISDIR(statbuf.st_mode)) {
            /* Found a directory, but ignore . and .. */
            if(strcmp(“.”,entry->d_name) == 0 ||
                 strcmp(“..”,entry->d_name) == 0)
                 continue;
            printf(“%*s%s//n”,depth,””,entry->d_name);
            /* Recurse at a new indent level */
            printdir(entry->d_name,depth+4);
        }
        else printf(“%*s%s/n”,depth,””,entry->d_name);
    }
    chdir(“..”);
    closedir(dp);
}

2 现在我们开始主函数

int main()
{
    printf(“Directory scan of /home:/n”);
    printdir(“/home”,0);
    printf(“done./n”);
    exit(0);
}

程序的处理结果输出如下所示:

$ printdir
Directory scan of /h
neil/
    .Xdefaults
    .Xmodmap
    .Xresources
    .bash_history
    .bashrc
    .kde/
        share/
            apps/
                konqueror/
                     dirtree/
                         public_html.desktop
                     toolbar/
                     bookmarks.xml
                     konq_history
                kdisplay/
                     color-schemes/
    BLP3/
        Gnu_Public_License
        chapter04/
            argopt.c
            args.c
        chapter03/
            file.out
            mmap.c
            printdir
done.

工作原理

大 多数的动作位于printdir函数中,所以那将是我们查看的地方。通过使用opendir来确定指定的目录是否存在来进行一些初始的检测, printdir在指定的目录上调用chdir函数。当由readdir返回实体不为空时,程序会进行检测确定其是否为一个目录。如果不是,则使用 depth缩进来打印文件实体。

如果这个实体是一个目录,我们就需要进行一些递归操作。在.与..实体(当前目录与父目录)被忽略以后, printdir函数会调用其自身,并且再次进行同样的处理操作。那么如何跳出这个循环呢?一旦while循环结束,chdir("..")函数调用将返 回目录树,从而以先的列表操作就会继续。调用closedir(dp)可以确保打开目录流的数目不会高于其所需要的数目。

为了简略的介绍一下第四章将会讨论的Linux环境,我们来看一下使得程序更为通用的一个方法。程序有限制,是因为他指定为/home/neil目录。通过下面的对main函数的更改,我们可以将其变为一个更为有用的目录浏览器:

int main(int argc, char* argv[])
{
    char *topdir = “.”;
    if (argc >= 2)
      topdir=argv[1];
    printf(“Directory scan of %s/n”,topdir);
    printdir(topdir,0);
    printf(“done./n”);
    exit(0);
}

我们改变了三行代码并且添加了五行,现在他就是一个带有目录名可选参数的通用程序了,其默认为当前目录。我们可以用下面的命令来运行:

$ printdir2 /usr/local | more

输出将会进行分页,从而用户可以在输出之中进行分页浏览。这样,用户就会具有了一个方便小巧的通用目录树浏览器。还可以有一些小的修改,我们可以添加空白使用数据,显示的限制深度,等待。

错误

正 如我们所看到的,这一章所描述的许多系统函数与调用都会因为各种原因而失败。当出现这种情况时,他们通过设置外部变量errno来指示其失败原因。许多不 同的库使用这个变量作为报告问题的标准方式。但是在程序指出问题之后,程序必须立即测试errno变量的值,因为他会被下一个函数调用所覆盖,尽管这个函 数本身并没有失败。

错误值与其相关的意义列在头文件errno.h中。他们包括:

EPERM:操作不允许
ENOENT:没有这个文件或目录
EINTR:系统调用中断
EIO:I/O错误
EBUSY:设备或资源忙
EEXIST:文件存在
EINVAL:参数不可用
EMFILE:太多的打开文件
ENODEV:没有这个设备
EISDIR:是一个目录
ENOTDIR:不是一个目录

当发生错误时,有一对十分有用的函数来报告错误:strerror与perror。

strerror

strerror函数将一个错误号映射为一个描述错误类型的字符串。这对于记录错误条件十分有用。

其语法如下:

#include <string.h>
char *strerror(int errnum);

perror

perror函数也将所报告的errno映射为一个字符串,并且打印到标准错误流。他以一个指定的字符串s(如果不为空)开始,然后是一个冒号与空格。

其语法如下:

#include <stdio.h>
void perror(const char *s);

例如:

perror(“program”);

会在标准错误输出上得到下面的输出:

program: Too many open files

/proc文件系统

在这一章的前面,我们提到过Linux将大多数内容看作文件,并且在文件系统中存在硬件设备文件。/dev文件被用来以一种使用低层系统调用的特殊方式来访问硬件。

控制硬件的软件驱动通常可以以特定的方式进行配置,或者是可以报告信息。例如,一个磁盘控制器可以配置使用特定的DMA模式。一个网卡可以报告其是否是高速,多路连接。

与设备驱动进行通信的程序在过去较为常见。例如,hdparm可以配置一些磁盘参数,而ifconfig可以报告其网络参数。在近些年,更为流行的方式是提供一个更为方便的方法来访问驱动信息,而且事实上,在Linux内核的各种元素中已经包含了这些通信。

Linux提供了一个特殊的文件系统,procfs,通常其以目录/proc的形式出现。他包含许多特殊的文件,可以允许高层访问驱动器与内核信息。程序只有要正确的访问权限就可以读取或是写入这些文件来得到信息或是设置参数。

/proc中出现的文件会因系统的不同而不同,而更多的包含在Linux发行版本中作为更多驱动器与程序支持的procfs文件系统。在这里,我们将会看一些其中比较常见的文件,并且简要的讨论其用法。

在编写这一章所使用的计算机上浏览/proc目录会得到下面的一些实体信息:

1/  1377/ 1771/ 951/ cpuinfo modules
10/ 1401/ 1777/ 961/ devices mounts@
1007/ 1414/ 1778/ 966/      dma         mtrr
1023/ 1457/ 2/    968/      driver/     net/
1053/ 1460/ 3/    969/      execdomains partitions
1056/ 1463/ 385/  970/      fb          pci
1059/ 1465/ 388/  971/      filesystems scsi/
1061/ 1476/ 4/    974/      fs/         self@
1071/ 1477/ 424/  975/      ide/        slabinfo
1077/ 1479/ 4775/ 976/      interrupts  splash
1079/ 1480/ 4850/ 977/      iomem       stat
1080/ 1482/ 496/  978/      ioports     swaps
1082/ 1484/ 5/    979/      irq/        sys/
1086/ 1486/ 535/  980/      isapnp      sysvipc/
1090/ 1491/ 6/    982/      kcore       tty/
1093/ 1494/ 625/  983/      kmsg        uptime
1095/ 1495/ 7/    999/      ksyms       version
1096/ 1496/ 75/   apm       loadavg     video/
1100/ 1502/ 8/    asound/   locks
1101/ 1503/ 884/  buddyinfo lvm/
1104/ 1545/ 905/  bus/      mdstat
1118/ 1546/ 917/  cmdline   meminfo
1119/ 1770/ 932/  config.gz misc

在许多情况下,这些文件可以被读取并给出状态信息。例如,/proc/cpuinfo会给出处理器的详细信息:

$ cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 6
model name      : Celeron (Mendocino)
stepping        : 0
cpu MHz         : 451.028
cache size      : 128 KB
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 2
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 sep mtrr pge mca cmov pat
pse36 mmx fxsr
bogomips        : 897.84

相似的,/proc/meminfo与/proc/version会分别给出有关内存使用与内核版本的相关信息:

$ cat /proc/meminfo
        total:    used:    free:    shared: buffers: cached:
Mem: 527392768 240873472 286519296       0 8331264 134004736
Swap: 139788288         0 139788288
MemTotal:       515032 kB
MemFree:        279804 kB
MemShared:           0 kB
Buffers:          8136 kB
Cached:         130864 kB
SwapCached:          0 kB
Active:         101208 kB
Inactive:       106056 kB
HighTotal:           0 kB
HighFree:            0 kB
LowTotal:       515032 kB
LowFree:        279804 kB
SwapTotal:      136512 kB
SwapFree:       136512 kB
BigFree:             0 kB
$ cat /proc/version
Linux version 2.4.19-4GB (root@Pentium.suse.de) (gcc version 3.2) #1 Wed Nov 27
00:56:40 UTC 2002

更多的特定内核函数的信息可以在/proc的子目录中查找到。例如,我们可以由/proc/net/sockstat得到网络套接口的使用数据:

$ cat /proc/net/sockstat
sockets: used 246
TCP: inuse 20 orphan 0 tw 0 alloc 22 mem 11
UDP: inuse 3
RAW: inuse 0
FRAG: inuse 0 memory 0

/proc中的一些实体可以进行读写。例如,所有运行程序同时可以打开的文件数目是一个Linux内核参数。当前的值可以由/proc/sys/fs/file-max来读取:

$ cat /proc/sys/fs/file-max
52428

在这里其值为52428。如果我们需要增加这上值,我们可以通过写入同样的文件来做到。如果我们正运行一个特殊的程序套件,那么也许我们就需要这样做,例如使用许多表的数据库系统,这需要同时打开许多文件。

注意:写入/proc文件需要超级访问权限。当写入/proc文件时我们要小心,如果我们写入了不正确的值就会引起严重的问题。

如果我们将系统文件处理的限制增加到60000,我们可以简单的向file-max写入这个新的限制数目:

# echo 60000 >/proc/sys/fs/file-max

现在我们可以重新读取这个文件,我们就会看到新值:

$ cat /proc/sys/fs/file-max
60000

/proc下具有数字名字的子目录用来提供访问关于运行程序的信息。我们将会第11章了解到更多的关于程序如何执行为进程的相关信息。

但是现在,我们只需要注意第一个进程具有唯一的一个标识符:在1到32000之间的一个数值。ps命令提供了当前运行进程的一个列表。例如,在编写这一章时:

neil@beast:~/BLP3/chapter03> ps
  PID TTY          TIME CMD
 1104 pts/1    00:00:00 bash
 1503 pts/2    00:00:01 bash
 1771 pts/4    00:00:00 bash
 4991 pts/2    00:00:01 emacs
 4994 pts/2    00:00:00 ps
neil@beast:~/BLP3/chapter03>

在这里我们可以看到一些运行bash shell的终端会话,一个运行Emacs文件编辑器的编辑会话。我们可以通过查看/proc了解更多的关于Emacs会话的详细信息。

在这里Emacs进程的标识为4991,所以我们需要查看/proc/4991来得到更为详细的信息:

$ ls -l /proc/4991
total 0
-r--r--r--    1 neil users 0 2003-02-09 12:45 cmdline
lrwxrwxrwx    1 neil users 0 2003-02-09 12:45 cwd -> /home/neil/BLP3/chapter03
-r--------    1 neil users 0 2003-02-09 12:45 environ
lrwxrwxrwx    1 neil users 0 2003-02-09 12:45 exe -> /usr/bin/emacs
dr-x------    2 neil users 0 2003-02-09 12:45 fd
-rw-------    1 neil users 0 2003-02-09 12:45 mapped_base
-r--r--r--    1 neil users 0 2003-02-09 12:45 maps
-rw-------    1 neil users 0 2003-02-09 12:45 mem
-r--r--r--    1 neil users 0 2003-02-09 12:45 mounts
lrwxrwxrwx    1 neil users 0 2003-02-09 12:45 root -> /
-r--r--r--    1 neil users 0 2003-02-09 12:45 stat
-r--r--r--    1 neil users 0 2003-02-09 12:45 statm
-r--r--r--    1 neil users 0 2003-02-09 12:45 status

在这里,我们可以看到各种特殊文件来告诉我们这个进程中所发生的事情。

我 们可以看到程序/usr/bin/emacs正在运行,而其当前工作目录为/home/neil/BLP3/chpter03。也可以读取这个目录中的其 他文件来查看其启动所需要的命令以及其所具有的shell环境。cmdline与environ文件作为一系列的非终端字符串来提供这些信息,所以我们查 看他们时需要小心。我们将会在第四章更为深入的讨论Linux环境。

$ od -c /proc/4991/cmdline
0000000   e   m   a   c    s /0 d r a f t 2 . t x t
0000020 /0
0000021

在这里,我们可看到Emacs是由命令行emacs draft2.txt来启动的。

fd 子目录提供了关于进程打开的正使用的文件描述符的信息。这个信息十分有用,可以用来确定一个程序一次打开了多少个文件。每一个打开的文件描述符有一个实 体;其名字与文件描述号相匹配。在我们这个例子中,我们可以看到Emacs打开描述符0,1,2,这正是我们所期望的。这是标准输入,输出,以及错误描述 符。尽管此时他正编辑一个文件,他并没有由这个进程保持打开,所以,并不会显示在这里。

$ ls /proc/4991/fd
0 1 2

高级主题:fcntl与mmap

在这里,我们半会讨论一对我们也许会跳过的主题,因为他们很少被用到。正如我们所说的,我们将其放在这里作为引用,因为他们可以为一些技巧问题提供一些简单的解决办法。

fcntl

fcntl系统调用提供了更多的方法来处理底层文件描述符。

#include <fcntl.h>
int fcntl(int fildes, int cmd);
int fcntl(int fildes, int cmd, long arg);

我们可以使用fcntl系统调用在的打开的文件描述符上执行各种操作,包括复制,获取与设置文件描述符标记,获取与设置文件状态标记,以及管理文件锁。

各种操作是由fcntl.h中定义的命令参数cmd的不同值为选择的。依据于所选择的命令,系统调用需要第三个参数,arg:

fcntl(fildes,F_DUPFD,newfd):这个调用会返回一个新的文件描述符,这个文件描述符的值等于或大于newfd的值。新的文件描述符是描述符fildes的一个拷贝。依据打开的文件数目以及newfd的值,这与dup(fildes)同样高效。

fcntl(fildes,F_GETFD):这个调用会返回在fcntl.h中定义的文件描述符标记。这些包括FD_CLOEXEC,这会确定在成功的调用了系统调用的exec家族中的一个后是否关闭。

fcntl(fildes,F_SETFD,flags):这个调用用来调用文件描述符标记,通常只是FD_CLOEXEC。

fcntl (fildes,F_GETFL)与fcntl(fildes,F_SETFL,flags):这些函数分别用来获取与设置文件状态标记与访问模式。我们 可以通过使用fcntl.h中定义的O_ACCMODE掩码来得到访问模式。其他的标记包括传递给使用O_CREAT的open的第三个参数。注意,我们 不能设置所有的标记。通常而言,我们不能使用fcntl来设置文件权限。

我们可以借助fcntl实现咨询文件锁。查看手册页第2节我们可以得到更多的信息,或是第七章,我们将会那里讨论文件锁。

mmap

Unix提供了一个非常有用的程序可以允许程序共享内容,而一个好消息就是这已经包含在2.0以及以后的Linux内核中。mmap函数可以设置一段两个或是多个程序可以读写的内存。一个程序所优的更改可以为另一个程序看到。

我们可以使用同样的程序来操作文件。我们可以使得一个磁盘文件的实体内容看起像是内存中的一个数组。如果文件由C结构可以描述的记录组成,我们可以使用结构数组访问来更新文件。

这是通过具有特殊访问集合的虚拟内存段的使用来做到的。读取与写入段会引起操作系统读取或是写入磁盘文件的相应部分。

mmap函数创建一个指针指向一个与文件内容相关的内存区域,这个文件内容可以由一个打开的文件描述符来访问。

#include <sys/mman.h>
void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);

我们可以通过传递off参数来修改由共享段访问的文件数据的起始处。可以访问的数据量(例如,内存段的长度)是通过len参数来设置的。

我们可以使用addr参数来请求一个特定的内存地址。如果为空,结果指针是自动分配的。这是推荐的用法,否则很难移植;系统的变量地址空间是变化的。

prot参数用来设置内存段的访问权限。这是下面这些常量的按位或:
PROT_READ:段可读
PROT_WRITE:段可写
PROT_EXEC:段可执行
PROT_NONE:段不可访问

flags参数控制程序所做的到段的更改是如何反射的:
MAP_PRIVATE    段是私有的,改变是局部的
MAP_SHARED    段的改变反映到文件
MAP_FIXED    段必须在指定的地址addr

msync函数使得内存段的部分或是全部改变写回(或是读取)所映射的文件:

#include <sys/mman.h>
int msync(void *addr, size_t len, int flags);

要更新的段部分是由传递的起始地址,addr以及长度,len是来决定的。flags参数控制如何执行这些更新。

MS_ASYNC    执行异步写
MS_SYNC        执行同步写
MS_INVALIDATE    由文件读取数据

munmap函数释放内存段。

#include <sys/mman.h>
int munmap(void *addr, size_t len);

下面的程序,mmap_eg.c,显示了一个使用mmap与数组格式访问进行更新的结构文件。2.0以前的Linux并不能完全支持mmap的使用。这个程序可以在Sun Solaris以及其他的系统正确工作。

1 我们由定义ERCORD结构与创建NRECOREDS版本开始,每一个记录他们的数字。这些添加到文件records.dat中。

#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdlib.h>
typedef struct {
    int integer;
    char string[24];
} RECORD;
#define NRECORDS (100)
int main()
{
    RECORD record, *mapped;
    int i, f;
    FILE *fp;
    fp = fopen(“records.dat”,”w+”);
    for(i=0; i<NRECORDS; i++) {
        record.integer = i;
        sprintf(record.string,”RECORD-%d”,i);
        fwrite(&record,sizeof(record),1,fp);
    }
    fclose(fp);

2 我们现在改变记录43到143的整数值,并且写第43个记录字符串处:

fp = fopen(“records.dat”,”r+”);
fseek(fp,43*sizeof(record),SEEK_SET);
fread(&record,sizeof(record),1,fp);
record.integer = 143;
sprintf(record.string,”RECORD-%d”,record.integer);
fseek(fp,43*sizeof(record),SEEK_SET);
fwrite(&record,sizeof(record),1,fp);
fclose(fp);

3 为了将整数值改变为243(并且更新记录字符串),我们将这些记录映射到内存,并且访问第43个记录,在这里使用内存映射:

  f = open(“records.dat”,O_RDWR);
  mapped = (RECORD *)mmap(0, NRECORDS*sizeof(record),
                        PROT_READ|PROT_WRITE, MAP_SHARED, f, 0);
  mapped[43].integer = 243;
  sprintf(mapped[43].string,”RECORD-%d”,mapped[43].integer);
  msync((void *)mapped, NRECORDS*sizeof(record), MS_ASYNC);
  munmap((void *)mapped, NRECORDS*sizeof(record));
  close(f);
  exit(0);
}

在第13章,我们将会看到另一个共享内存程序:System V共享内存。

总结

在这一章,我们了解了Linux如何提供直接访问文件与设备。我们也了解了库函数是如何构建在这些底层的函数上来为程序问题提供灵活的解决方案的。结果,我们可以只用几行代码就可以编写出一个相当强大的目录浏览例程。

我们现在已经了解了关于文件与目录操作的足够知识,可以使用更为结构化的基于文件的解决方案将我们在第2章结束时所编写的CD程序转换为C程序。然而,此时,我们并不能为程序添加新的功能,所以我们会在了解了如何处理屏幕与键盘之后再进行重写,而这将是下两章的内容。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux文件操作(三) 的相关文章

  • 如何在数组中存储包含双引号的命令参数?

    我有一个 Bash 脚本 它生成 存储和修改数组中的值 这些值稍后用作命令的参数 对于 MCVE 我想到了任意命令bash c echo 0 0 echo 1 1 这解释了我的问题 我将用两个参数调用我的命令 option1 without
  • 如何使用GDB修改内存内容?

    我知道我们可以使用几个命令来访问和读取内存 例如 print p x 但是如何更改任何特定位置的内存内容 在 GDB 中调试时 最简单的是设置程序变量 参见GDB 分配 http sourceware org gdb current onl
  • nslookup 报告“无法解析 '(null)': 名称无法解析”,尽管它成功解析了 DNS 名称

    我在 ubuntu 上 并且正在运行 docker 默认桥接网络 我有 Zookeeper kafka 的容器化版本 以及我编写的与 kafka 对话的应用程序 I do a docker exec it
  • PHP 从命令行启动 gui 程序,但 apache 不启动

    首先 我阅读了有类似问题的人的一些帖子 但所有答案都没有超出导出 DISPLAY 0 0 和 xauth cookies 这是我的问题 提前感谢您的宝贵时间 我开发了一个小库 它使用 OpenGL 和 GLSL 渲染货架 过去几天我将它包装
  • 如何将目录及其子目录中的所有 PDF 文件复制到一个位置?

    如何全部复制PDF文件从目录及其子目录到单个目录 实际上还有更多的文件 并且深度有些任意 假设四个目录的最大深度是公平的 我想这些文件需要重命名 如果a pdf例如 位于多个目录中 因为我会adding https ebooks stack
  • Linux 内核标识符中前导和尾随下划线的含义是什么?

    我不断遇到一些小约定 比如 KERNEL Are the 在这种情况下 是内核开发人员使用的命名约定 还是以这种方式命名宏的语法特定原因 整个代码中有很多这样的例子 例如 某些函数和变量以 甚至 这有什么具体原因吗 它似乎被广泛使用 我只需
  • Linux:如何从特定端口发送TCP数据包?

    如何打开原始套接字以从特定 TCP 端口发送 我希望所有连接始终来自临时端口以下的一系列端口 如果您正在使用raw套接字 然后只需在数据包标头中填写正确的 TCP 源端口即可 相反 如果您使用 TCP 套接字接口 socket connec
  • 安装J语言的JQt IDE,出现错误

    我一直按照这里的说明进行操作 http code jsoftware com wiki System Installation Linux http code jsoftware com wiki System Installation L
  • C语言中如何通过内存地址映射函数名和行号?

    如何用 GCC 中的内存地址映射回函数名称和行号 即假设一个 C 语言原型 void func Get the address of caller maybe this could be avoided MemoryAddress get
  • docker容器大小远大于实际大小

    我正在尝试从中构建图像debian latest 构建后 报告的图像虚拟大小来自docker images命令为 1 917 GB 我登录查看尺寸 du sh 大小为 573 MB 我很确定这么大的尺寸通常是不可能的 这里发生了什么 如何获
  • 我的线程图像生成应用程序如何将其数据传输到 GUI?

    Mandelbrot 生成器的缓慢多精度实现 线程化 使用 POSIX 线程 Gtk 图形用户界面 我有点失落了 这是我第一次尝试编写线程程序 我实际上并没有尝试转换它的单线程版本 只是尝试实现基本框架 到目前为止它是如何工作的简要描述 M
  • ftrace:仅打印trace_printk()的输出

    是否可以只转储trace printk 输出于trace文件 我的意思是过滤掉函数跟踪器 或任何其他跟踪器 中的所有函数 一般来说 您可以在选项目录中关闭选项 sys kernel debug tracing options Use ls显
  • Emacs如何自动完成C上包含文件的单词?

    如何使 Emacs 完成 C 包含文件中的单词 include
  • 在脚本内使用不带密码的 sudo

    由于某种原因 我需要作为用户在没有 sudo 的情况下运行脚本 script sh 该脚本需要 root 权限才能工作 我认为将 sudo 放入 script sh 中是唯一的解决方案 让我们举个例子 script sh bin sh su
  • 如何确保应用程序在 Linux 上持续运行

    我试图确保脚本在开发服务器上保持运行 它会整理统计数据并提供网络服务 因此它应该会持续存在 但一天中有几次 它会因未知原因而消失 当我们注意到时 我们只需再次启动它 但这很麻烦 并且某些用户没有权限 或专有技术 来启动它 作为一名程序员 我
  • Org-Mode 中的 FlySpell 可以像 auctex 一样识别 Latex 语法

    原始回复 我试图弄清楚在 auctex 模式下乳胶如何在打开 Flyspell 的情况下似乎不会突出显示任何乳胶功能 这是一个自定义词典文件还是如何实现的 这可以很容易地合并到组织模式文件中 这样它就不会突出显示将导出的插入乳胶代码吗 编辑
  • MySQL 中的创建/写入权限

    我的设备遇到一些权限问题SELECT INTO OUTFILE陈述 当我登录数据库并执行简单的导出命令时 例如 mysql gt select from XYZ into outfile home mropa Photos Desktop
  • 按进程名称过滤并记录 CPU 使用情况

    Linux 下有选项吗顶部命令 https www man7 org linux man pages man1 top 1 html我可以在哪里按名称过滤进程并将每秒该进程的 CPU 使用情况写入日志文件 top pgrep 过滤输出top
  • waitpid() 的作用是什么?

    有什么用waitpid 它通常用于等待特定进程完成 或者如果您使用特殊标志则更改状态 基于其进程 ID 也称为pid 它还可用于等待一组子进程中的任何一个 无论是来自特定进程组的子进程还是当前进程的任何子进程 See here http l
  • 快速像素绘图库

    我的应用程序以每像素的方式生成 动画 因此我需要有效地绘制它们 我尝试过不同的策略 库 但结果并不令人满意 尤其是在更高分辨率的情况下 这是我尝试过的 SDL 好的 但是慢 OpenGL 像素操作效率低下 xlib 更好 但仍然太慢 svg

随机推荐

  • Android框架源码分析——以Arouter为例谈谈学习开源框架的最佳姿势

    得意于众多项目和第三方库的开源 开发中使用几行代码即可实现复杂的功能 但使用只是源码库的搬运工 源码中真正牛逼的技术并不属于我们 所以对源码和开源库的学习成了Android开发者提升技能的必经之路 笔者也曾经认真学习了常用开源框架的原理和实
  • ant-design-vue 图片预览组件,支持旋转,放大缩小,下载

    图片预览组件 支持旋转 放大缩小 下载 图片预览组件 支持旋转 放大缩小 下载 复制代码
  • 【华为OD机试真题 Python】快速开租建站(100%通过)

    前言 本专栏将持续更新互联网大厂机试真题 并进行详细的分析与解答 包含完整的代码实现 希望可以帮助到正在努力的你 关于大厂机试流程 面经 面试指导等 如有任何疑问 欢迎联系我 wechat steven moda email nansun0
  • Promise的九大方法(resolve、reject、then、catch、finally、all、allSettled、race、any)你都用过那些?

    前言 定期复盘 今天我们来复习一下 Promise 的几个方法 分别是 Promise resolve Promise reject Promise then Promise catch Promise finally Promise al
  • linux怎样切换成root用户

    输入命令 su root 即可 如果是使用vagrant的话 密码默认为vagrant
  • 基于stm32f407VGT6控制WS2812的TIM1+PWM+DMA实现方式

    项目中使用到了ws2812灯带 作为产品的外观显示灯 经过开发之后 整理一下 仅供大家参考 WS2812B是一个集控制电路与发光电路于一体的智能外控LED光源 其外型与一个5050 LED灯珠相同 每个元件即为一个像素点 像素点内部包含了智
  • 达梦数据库ODBC连接异常问题

    一 ODBC介绍 ODBC 即开放数据库连接Open Database Connectivity 是为解决 异构数据库间的数据共享而产生的一种数据库访问接口标准 ODBC 为异构数据库访问提供统一接口 允许应用程序以SQL 为数据存取标准
  • linux内核参数注释与优化

    linux内核参数注释与优化 目录 1 linux内核参数注释 2 两种修改内核参数方法 3 内核优化参数生产配置 参数解释由网络上收集整理 常用优化参数对比了网上多个实际应用进行表格化整理 使查看更直观 学习linux也有不少时间了 每次
  • 拓扑排序(最大食物链计数、图文结合)

    拓扑排序 拓扑排序 topological sort 是指由某个集合上的一个偏序得到该集合上的一个全序的操作 拓扑排序常用来确定一个依赖关系集中 事物发生的顺序 拓扑排序是对有向无环图的顶点的一种排序 它使得如果存在一条从顶点A到顶点B的路
  • Eclipse使用教程

    Eclipse使用教程 目录 1 Eclipse的基本概念 2 Eclipse创建Java文件 3 eclipse 代码提示功能 4 快捷键的使用 5 代码自动生成功能 6 代码注释 7 代码重构 重点 下载软件 Eclipse官方网站 点
  • 最近的一些感想

    我正在经历入行以来规模最小的一个项目 但是我却要使用很多的复杂技术 我已经为它实现了一个微型状态机 接下来我还要研究规则引擎 甚至可能还要自定义通讯协议 麻雀虽小 五脏俱全 沟通永远是最重要 最困难的事情 可是我永远也无法说服任何人 谁都有
  • 算法题记录2:跳格子问题

    题目 存在一个数组 0 1 2 3 1 2 3 其中包含的数字可能相同可能不同 跳格子规则 不同的相邻数字只能一个一个跳 而相同的数字可以无视数组中的距离 一步即达 问题 问从初始位置到数组末尾需要跳多少次 示例 0 1 2 3 4 5 6
  • [深入研究4G/5G/6G专题-35]: URLLC-6-《中国联通5G URLLC技术白皮书3.0版本》解读-2-无线侧关键技术

    目录 第3章 URLLC关键技术之无线接入网技术 3 1 无线接入网技术 3 1 1 低延时增强技术
  • 分部积分题型总结笔记(分部积分超强拓展)

    分部积分在考研中的重要性不用多说了 是很多题目解题的关键 我从李林880 张宇1000题 汤家凤1800中 对分部积分常考的六类题型进行了总结 见下 分部积分的作用 基础好的可跳过 分部积分的初始表达式如下 u v d x u v u v
  • Python项目打包, docker build构建docker镜像, Docker Compose (Docker编配)

    重点摘要 将本地Python项目打包构建docker镜像 并在docker中运行 流程1 8 8 Docker Compose Docker编配 附录 其他常用docker命令 1 首先 完成本地Python的开发 测试 2 1 将项目依赖
  • QT5.9.3中debug问题:DirectWrite: CreateFontFaceFromHDC() failed (Unknown error 0x88985000.) for QFontDef

    今天在迁移同时的代码的时候遇到如下问题 从QT4 8 6迁移到QT5 9 3 MSVC2015 32bit DirectWrite CreateFontFaceFromHDC failed Unknown error 0x88985000
  • SD卡小结

    最近应老板要求 用mega328P做了一个小板用来将串口接收的数据存在SD卡中 主要是保存长时间的一个其他板子的串口log而做的一个小板子 停停顿顿将近2周才做完 中间还做了其他的事情 当然主要原因是水平有限 以前没怎么接触过SD卡和FAT
  • R语言构造扑克牌自动发牌,洗牌

    在R语言构建自动洗牌 发牌 要求 自动洗牌 发牌 任务一 创建一副牌 学会如何使用R的数据类型和数据结构 任务二 编写发牌和洗牌的函数 学习从一个数据集中抽取想要的数值 首先需要创建一副牌 不包括大小王 从R语言的数据对象来看 数据框最合适
  • 微信小程序实现GBK和UTF-8互转

    js虽然有第三方支持的GBK工具 但是小程序没有 而我开发中又需要进行格式的转化 就依据前人的经验做了一份出来 分为两部分 Decode js和Encode js 分别是GBK格式的二进制文件转化为UTF 8的String和反转 impor
  • Linux文件操作(三)

    mkdir和rmdir 我们可以使用mkdir和rmdir来创建和移除目录 其语法如下 include