如何在Windows和Linux系统上监听文件夹的变动?

news2025/2/23 10:42:14

文章目录

  • 如何在Windows和Linux系统上监听文件夹的变动?
  • 读写文件
  • 文件系统的操作
  • 缓冲和流
  • 文件改变事件

如何在Windows和Linux系统上监听文件夹的变动?

libuv库实现了监听整个文件夹的修改。本文详细介绍libuv库文件读写和监听的的实现方法。libuv库开发了多个 uv_fs_* 函数和 uv_fs_t 结构体可实现文件系统读/写。libuv 文件系统操作与套接字操作不同。套接字操作使用操作系统提供的非阻塞操作。文件系统操作在内部使用阻塞函数,但在需要应用程序交互时在线程池中调用这些函数并通知在事件循环中注册的观察者。所有文件系统函数都有两种形式 - 同步和异步。如果回调为空,同步表单会自动被调用(并阻塞)。函数的返回值是 libuv 错误代码。这通常仅对同步调用有用。当传递回调并且返回值为0时调用异步形式。

在这里插入图片描述

读写文件

获取文件描述符可以使用

int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb)

flags 和 mode 是标准 Unix 标志。 libuv 负责转换为适当的 Windows 标志。文件描述符使用以下命令关闭:

int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)

文件系统操作回调函数的形式:

void callback(uv_fs_t* req);

下文展示 cat 的简单实现。我们首先注册文件打开时的回调:

void on_open(uv_fs_t *req) {
    assert(req == &open_req);
    if (req->result >= 0) {
        iov = uv_buf_init(buffer, sizeof(buffer));
        uv_fs_read(uv_default_loop(), &read_req, req->result, &iov, 1, -1, on_read);
    } else {
        fprintf(stderr, "error opening file %s\n", uv_strerror((int)req->result));
    }
}

uv_fs_tresult 字段是 uv_fs_open 回调情况下的文件描述符。如果文件成功打开,我们就开始读取它。

void on_read(uv_fs_t *req) {
    if (req->result < 0) {
        fprintf(stderr, "Read error: %s\n", uv_strerror(req->result));
    } else if(req->result == 0) {
        uv_fs_t close_req;
        uv_fs_close(uv_default_loop(), &close_req, open_req.result, NULL);
    } else if(req->result > 0) {
        iov.len = req->result;
        uv_fs_write(uv_default_loop(), &write_req, 1, &iov, 1, -1, on_write);
    }
}

在读取调用的情况下,您应该传递一个初始化的缓冲区,该缓冲区将在触发读取回调之前填充数据。 uv_fs_* 操作几乎直接映射到某些 POSIX 函数,因此在这种情况下 EOF 通过 result 为 0 来指示。对于流或管道, UV_EOF 常量将作为状态传递。

在这里您可以看到编写异步程序时的常见模式。 uv_fs_close() 调用是同步执行的。通常,一次性任务或作为启动或关闭阶段的一部分完成的任务是同步执行的,因为当程序执行其主要任务并处理多个 I/O 源时,我们对快速 I/O 感兴趣。对于单独任务,性能差异通常可以忽略不计,并且可能会导致代码更简单。

使用 uv_fs_write() 操作文件系统也同样简单。写入完成后将触发您的回调。在我们的例子中,回调只是驱动下一次读取。因此,读取和写入通过回调同步进行。

void on_write(uv_fs_t *req) {
    if (req->result < 0) {
        fprintf(stderr, "Write error: %s\n", uv_strerror((int)req->result));
    } else {
        uv_fs_read(uv_default_loop(), &read_req, open_req.result, &iov, 1, -1, on_read);
    }
}

由于文件系统和磁盘驱动器的性能配置方式,“成功”的写入可能尚未提交到磁盘。最后用main函数串联起来:

int main (int argc, char **argv) {
    uv_fs_open(uv_default_loop(), &open_req, argv[1], O_RDONLY, 0, on_open);
    uv_run(uv_default_loop(), UV_RUN_DEFAULT);
    uv_fs_req_cleanup(&open_req);
    uv_fs_req_cleanup(&read_req);
    uv_fs_req_cleanup(&write_req);
    return 0;
}

文件系统的操作

所有标准文件系统操作(如 unlinkrmdirstat 均支持异步,并具有直观的参数顺序。它们遵循与读/写/打开调用相同的模式,在 uv_fs_t.result 字段中返回结果。完整列表:

int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb);
int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb);
int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb);
int uv_fs_copyfile(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb);
int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb);
int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb);
int uv_fs_mkstemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb);
int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb);
int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent);
int uv_fs_opendir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb);
int uv_fs_closedir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb);
int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb);
int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, int64_t offset, uv_fs_cb cb);
int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb);
int uv_fs_access(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb);
int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb);
int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb);
int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb);
int uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb);
int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb);
int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb);
int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb);
int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
int uv_fs_statfs(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);

缓冲和流

libuv 中的基本 I/O 句柄是流 ( uv_stream_t )。 TCP 套接字、UDP 套接字以及文件 I/O 和 IPC 的管道都被视为流子类。使用每个子类的自定义函数初始化流,然后使用

int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb);
int uv_read_stop(uv_stream_t*);
int uv_write(uv_write_t* req, uv_stream_t* handle,
             const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);

基于流的函数比文件系统的函数更容易使用,并且当 uv_read_start() 被调用一次时,libuv将自动从流中读取,直到 uv_read_stop() 被调用。数据的读写性能的重点是缓冲区 —— uv_buf_t 。这只是一个指向字节 ( uv_buf_t.base ) 和长度 ( uv_buf_t.len ) 的指针的集合。 uv_buf_t 是轻量级的并且按值传递。需要管理的是实际字节,这些字节必须由应用程序分配和释放。**缓冲区不是万能的。**有时时候缓冲区并不适合。为了演示流,我们需要使用 uv_pipe_t 。这允许流式传输本地文件 2。这是一个使用 libuv 的简单 tee 实用程序。异步执行所有操作显示了事件 I/O 的强大功能。两次写入不会互相阻塞,但我们必须小心复制缓冲区数据,以确保在写入缓冲区之前不会释放缓冲区。我们开始在我们需要的文件上打开管道。默认情况下,通往文件的 libuv 管道以双向方式打开。下文以 uvtee 程序举例说明。

int main(int argc, char **argv) {
    loop = uv_default_loop();

    uv_pipe_init(loop, &stdin_pipe, 0);
    uv_pipe_open(&stdin_pipe, 0);

    uv_pipe_init(loop, &stdout_pipe, 0);
    uv_pipe_open(&stdout_pipe, 1);

    uv_fs_t file_req;
    int fd = uv_fs_open(loop, &file_req, argv[1], O_CREAT | O_RDWR, 644, NULL);
    uv_pipe_init(loop, &file_pipe, 0);
    uv_pipe_open(&file_pipe, fd);

    uv_read_start((uv_stream_t*)&stdin_pipe, alloc_buffer, read_stdin);

    uv_run(loop, UV_RUN_DEFAULT);
    return 0;
}

对于使用命名管道的 IPC, uv_pipe_init() 的第三个参数应设置为 1。这在流程中有所介绍。 uv_pipe_open() 调用将管道与文件描述符关联起来,在本例中是 0 (标准输入)。我们开始监控 stdin 。当需要新的缓冲区来保存传入数据时,将调用 alloc_buffer 回调。 read_stdin 将使用这些缓冲区进行调用。

void free_write_req(uv_write_t *req) {
    if (nread < 0){
        if (nread == UV_EOF){
            // end of file
            uv_close((uv_handle_t *)&stdin_pipe, NULL);
            uv_close((uv_handle_t *)&stdout_pipe, NULL);
            uv_close((uv_handle_t *)&file_pipe, NULL);
        }
    } else if (nread > 0) {
        write_data((uv_stream_t *)&stdout_pipe, nread, *buf, on_stdout_write);
        write_data((uv_stream_t *)&file_pipe, nread, *buf, on_file_write);
    }

    // OK to free buffer as write_data copies it.
    if (buf->base)
        free(buf->base);
}

标准的 malloc 在这里就足够了,但您可以使用任何内存分配方案。例如,node.js 使用自己的slab 分配器将缓冲区与V8 对象关联起来。任何错误时读取回调 nread 参数都小于 0。此错误可能是 EOF,在这种情况下,我们使用通用关闭函数 uv_close() 关闭所有流,该函数根据其内部类型处理句柄。否则 nread 是一个非负数,我们可以尝试将那么多字节写入输出流。最后记住,缓冲区分配和释放是应用程序的责任,因此我们释放数据。

如果分配内存失败,分配回调可能会返回长度为零的缓冲区。在这种情况下,调用读取回调时会出现错误 UV_ENOBUFS。不过,libuv 将继续尝试读取流,因此如果您想在分配失败时停止,则必须显式调用 uv_close() 。读取回调可以用 nread = 0 调用,表明此时没有任何内容可读取。大多数应用程序都会忽略这一点。

void on_stdout_write(uv_write_t *req, int status) {
    free_write_req(req);
}

void on_file_write(uv_write_t *req, int status) {
    free_write_req(req);
}

void write_data(uv_stream_t *dest, size_t size, uv_buf_t buf, uv_write_cb cb) {
    write_req_t *req = (write_req_t*) malloc(sizeof(write_req_t));
    req->buf = uv_buf_init((char*) malloc(size), size);
    memcpy(req->buf.base, buf.base, size);
    uv_write((uv_write_t*) req, (uv_stream_t*)dest, &req->buf, 1, cb);
}

write_data() 复制从读取中获得的缓冲区。该缓冲区不会传递到写入完成时触发的写入回调。为了解决这个问题,我们将写入请求和缓冲区包装在 write_req_t 中,并在回调中将其解开。我们制作一个副本,以便可以独立地从对 write_data 的两次调用中释放两个缓冲区。虽然这样的演示程序可以接受,但您可能需要更智能的内存管理,例如任何主要应用程序中的引用计数缓冲区或缓冲区池。

如果您的程序要与其他程序一起使用,它可能会有意或无意地写入管道。这使得它很容易在收到 SIGPIPE 时中止。有一个好的解决办法是在应用程序的初始化阶段插入信号处理代码:signal(SIGPIPE, SIG_IGN)

文件改变事件

所有现代操作系统都提供 API 来监视各个文件或目录,并在文件被修改时收到通知。 libuv 封装了常见的文件更改通知库(Linux 上的 inotify、Darwin 上的 FSEvents、BSD 上的 kqueue、Windows 上的 ReadDirectoryChangesW、Solaris 上的事件在Cygwin工具链上不受支持)。这是 libuv 中比较不一致的部分之一。文件更改通知系统本身在不同平台上差异很大,因此让所有内容在任何地方都正常工作是很困难的。为了进行演示,我将构建一个简单的实用程序,只要任何监视的文件发生更改,该实用程序就会运行命令。目前此示例仅适用于 OSX 和 Windows。参考uv_fs_event_start函数的注释。

int main(int argc, char **argv) {
    if (argc <= 2) {
        fprintf(stderr, "Usage: %s <command> <file1> [file2 ...]\n", argv[0]);
        return 1;
    }

    loop = uv_default_loop();
    command = argv[1];

    while (argc-- > 2) {
        fprintf(stderr, "Adding watch on %s\n", argv[argc]);
        uv_fs_event_t *fs_event_req = malloc(sizeof(uv_fs_event_t));
        uv_fs_event_init(loop, fs_event_req);
        // The recursive flag watches subdirectories too.
        uv_fs_event_start(fs_event_req, run_command, argv[argc], UV_FS_EVENT_RECURSIVE);
    }

    return uv_run(loop, UV_RUN_DEFAULT);
}

第三个参数是要监视的实际文件或目录。最后一个参数 flags 可以是:

/*
 * Flags to be passed to uv_fs_event_start().
 */
enum uv_fs_event_flags {
    UV_FS_EVENT_WATCH_ENTRY = 1,
    UV_FS_EVENT_STAT = 2,
    UV_FS_EVENT_RECURSIVE = 4
};

UV_FS_EVENT_WATCH_ENTRYUV_FS_EVENT_STAT 尚未执行任何操作。 UV_FS_EVENT_RECURSIVE 也将开始在支持的平台上监视子目录。回调函数接收以下参数:

  1. uv_fs_event_t *handle:句柄。句柄的 path 字段是设置手表的文件。
  2. const char *filename:如果正在监视目录,则这是已更改的文件。仅在 Linux 和 Windows 上非 null 。即使在这些平台上也可能是 null 。
  3. int eventsUV_RENAMEUV_CHANGE 之一,或两者的按位或。
  4. int status:如果 status < 0 ,则存在 libuv 错误。

在这里插入图片描述

在下面的示例中,程序只需打印参数并使用 system() 运行命令。

void run_command(uv_fs_event_t *handle, const char *filename, int events, int status) {
    char path[1024];
    size_t size = 1023;
    // Does not handle error if path is longer than 1023.
    uv_fs_event_getpath(handle, path, &size);
    path[size] = '\0';

    fprintf(stderr, "Change detected in %s: ", path);
    if (events & UV_RENAME)
        fprintf(stderr, "renamed");
    if (events & UV_CHANGE)
        fprintf(stderr, "changed");

    fprintf(stderr, " %s\n", filename ? filename : "");
    system(command);
}

在这里插入图片描述

作者:岬淢箫声
日期:2023年10月27日
版本:1.0
链接:http://caowei.blog.csdn.net

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1142620.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【计算机网络笔记】Cookie技术

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

Linux系统下安全控制策略SELinux解析

SELinux&#xff08;Security-Enhanced linux&#xff09;是增强版Linux&#xff0c;简称SELinux&#xff0c;它是一个Linux内核模块&#xff0c;也是Linux的一个安全子系统&#xff0c;主要以内核模块为支持&#xff0c;用户态程序进行权限策略管理。 背景 Linux系统下的roo…

镍氢充电管理芯片-IC AH2185

镍氢充电管理芯片AH2185&#xff1a;为便携式设备提供高效充电解决方案 随着科技的不断发展&#xff0c;便携式设备在人们的生活中扮演着越来越重要的角色。这些设备包括数码相机、电子词典、智能手机等&#xff0c;它们共同的特点是需要定期充电。为了满足这一需求&#xff0…

FFmpeg5.1.3编译动态库踩坑之旅(基于Linux虚拟机)

准备工作 环境准备 1.Windows安装Oracle VM VirtualBox 7.0.10&#xff0c;安装ubuntu-22.04.3。 坑一&#xff1a;无法往虚拟机里拖放复制文件&#xff0c;解决办法&#xff1a;登录Ubuntu虚拟机时切换到xorg方式登录&#xff0c;参考地址&#xff1a;Ubuntu Desktop 22.04…

LLVM学习笔记(55)

4.1.3. 降级 在前面的章节里&#xff0c;我们展示了目标机器特定节点与目标机器无关节点共存的一个图。你可能会问&#xff0c;如果这是指令选择的一个输入&#xff0c;为什么在SelectionDAG类中已经有一些目标机器特定的节点&#xff1f;要理解这&#xff0c;我们首先在下图概…

Kafka - 3.x 图解Broker总体工作流程

文章目录 Zk中存储的kafka的信息Kafka Broker总体工作流程1. broker启动后向zk中注册2. Controller谁先启动注册&#xff0c;谁说了算3. 由选举出来的Controller监听brokers节点的变化4. Controller决定leader选举5. Controller将节点信息上传到Zk中6. 其他Controller从zk中同步…

numpy和字符串格式化,用*画田字形状

numpy的字符型元素矩阵&#xff0c;可以方便画&#xff1b;直接python字符串手撕&#xff0c;也可以轻巧完成。 (本笔记适合熟悉循环和列表的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《…

鸿蒙ArkUI-X跨端应用开发,一套代码构建多平台应用

文章目录 一、项目介绍二、技术架构三、Gitee仓库地址四、ArkUI-X开发者文档五、快速开始——环境准备1、下载DevEco Studio&#xff0c;版本V4.0 Beta2以上2、打开DevEco&#xff0c;下载相关环境配置3、配置开发环境3.1、OpenHarmony SDK3.2、安装ArkUI-X SDK3.2、Android SD…

科聪协作(复合)移动机器人整体解决方案

协作&#xff08;复合&#xff09;移动机器人&#xff08;AGV/AMR&#xff09;相较传统工业机器人具有更加安全和简单的工作优势&#xff0c;具备较强的发展潜力。协作&#xff08;复合&#xff09;移动机器人安全性和操作的简洁性、灵活性不断提高,优势得到了充分发挥,在越来越…

浏览器事件循环 (event loop)

进程与线程 进程 进程的概念 进程是操作系统中的一个程序或者一个程序的一次执行过程&#xff0c;是一个动态的概念&#xff0c;是程序在执行过程中分配和管理资源的基本单位&#xff0c;是操作系统结构的基础。 简单的来说&#xff0c;就是一个程序运行开辟的一块内存空间&a…

Windows-Oracle19c 安装详解-含Navicate远程连接配置 - 同时连接Oracle11g和Oracle19c

文章目录 0 说明1 下载链接2 安装&#xff1a;一定要以管理员身份运行&#xff0c;不然后面有可能会报错。3 启动监听4. 登录Oracle4 Navicate远程连接-配置监听4.1 修改监听文件4.2 网络配置助手-配置本地监听端口4.3 Navicate连接成功 5 Navicate同时连接两个Oracle数据库 0 …

读高性能MySQL(第4版)笔记21_读后总结与感想兼导读

1. 基本信息 高性能MySQL&#xff1a;经过大规模运维验证的策略&#xff08;第4版&#xff09; High Performance MySQL, Fourth Edition [美] Silvia Botros(西尔维亚博特罗斯)&#xff1b;Jeremy Tinley(杰里米廷利) 电子工业出版社,2022年10月出版 1.1. 读薄率 书籍总字…

窗帘布艺经营配送小程序商城的效果如何

窗帘布艺覆盖生活中多个使用场景&#xff0c;可以说是必需品&#xff0c;由于需要客户提供尺寸乃至上门安装等&#xff0c;因此传统客户购买此类产品&#xff0c;一般会选择线下亲自购买&#xff0c;包括质感、论价、挑选等。 但随着互联网电商深入&#xff0c;线上销售和客户…

Java NIO 高并发开发

Java NIO 高并发开发 前言 Java NIO&#xff08;New I/O&#xff09;相比于传统的Java I/O&#xff08;BIO&#xff09;在高并发开发方面具有以下优势&#xff1a; 非阻塞模式&#xff1a;Java NIO使用非阻塞的I/O操作&#xff0c;允许一个线程管理多个通道&#xff08;Channe…

<多线程章节十> 定时器的使用方法以及定时器的模拟实现

文章目录 &#x1f490;专栏导读&#x1f4a1;Java标准库中的定时器类&#x1f4a1;模拟实现定时器 &#x1f490;专栏导读 本篇文章收录于多线程&#xff0c;也欢迎翻阅博主的其他文章&#xff0c;可能也会让你有不一样的收获&#x1f604; &#x1f342;JavaSE&#x1f337;多…

Studio One6.5新版本功能介绍及下载图文教程

studio one6更新了。studio one终于迎来了期待已久的6.5版本&#xff0c;增加了杜比全景声环绕声等混音模式&#xff0c;让我们混音更加方便&#xff01;Studio One 6破是一个功能完整的工作站&#xff0c;不止于专业的音乐制作和编辑&#xff0c;Studio One也是一个直播表演工…

计算机视觉 激光雷达结合无监督学习进行物体检测的工作原理

一、简述 激光雷达是目前正在改变世界的传感器。它集成在自动驾驶汽车、自主无人机、机器人、卫星、火箭等中。该传感器使用激光束了解世界,并测量激光击中目标返回所需的时间,输出是点云信息,利用这些信息,我们可以从3D点云中查找障碍物。 从自动驾驶汽车的角度看激光雷达…

MySQL启动后反复重新启动故障

MySQL版本为5.6.45 系统为Ubuntu 20.04 LTS 该服务器重启后&#xff0c;MySQL需要手动执行启动。 运行执行脚本后发现异常&#xff0c;如下图&#xff1a; 提示MySQL服务在不停重复启动。 反复使用ps -ef |grep mysql命令查看&#xff0c;发现mysql进程号一直在变化&#x…

ChatGLM推出第三代基座大模型在论文阅读、文档摘要和财报分析等方面提升超过50%推理成本降低一半...

“ 智谱AI发布了第三代基座大模型ChatGLM3&#xff0c;在模型性能、功能支持、开源序列等方面进行了全面升级。ChatGLM3在语义、数学、推理、代码、知识等不同角度的数据集上测评显示&#xff0c;具有在10B以下的基础模型中最强的性能。同时&#xff0c;ChatGLM3还支持多模态理…

数据库的概念和sql语句

数据&#xff1a;数字信息 据&#xff1a;就是属性 对一系列对象的具体属性的描述的集合 数据库&#xff1a;数据库就是用来组织&#xff08;各个数据之间是有关联。是按照规则组织起来的&#xff09;&#xff0c;存储和管理&#xff08;对数据的增删改查&#xff09;的仓库 …