进程与信号(三)

news2024/10/6 22:23:19

目录

一、前言

二、Signals

1、Signal Handling(ctrlc.c)

2、Sending Signals

(1)alarm.c

(2)A Robust Signals Interface

(3)ctrlc2.c

3、Signal Sets

(1)sigaction Flags

(2)Common Signal Reference


一、前言

进程和信号是 Linux 操作环境的基本组成部分。它们控制 Linux 和所有其他类 unix 计算机系统执行的几乎所有活动。了解 Linux 和 UNIX 如何管理进程对任何系统程序员、应用程序程序员或系统管理员都有好处。

在本中,我们将学习如何在 Linux 环境中处理进程,以及如何找出计算机在任何给定时间正在做什么。我们还将了解如何从我们自己的程序中启动和停止其他进程,如何使进程发送和接收消息,以及如何避免僵尸进程。特别是,我们将了解:

(1)进程的结构、类型和调度;

(2)以不同的方式启动新进程;

(3)父进程、子进程和僵尸进程;

(4)什么是信号以及如何使用它们。

二、Signals

信号是 UNIX 和 Linux 系统为响应某些条件而生成的事件,进程在接收到这些条件后可能反过来采取一些行动。我们使用术语 raise 表示信号的生成,使用术语 catch 表示信号的接收。信号由一些错误条件引发,例如内存段违规、浮点处理器错误或非法指令。它们是由 shell 和终端处理程序生成的,用于引起中断,也可以从一个进程显式地发送到另一个进程,作为传递信息或修改行为的一种方式。在所有这些情况下,编程接口是相同的。信号可以被提出、捕捉和采取行动,或者 (至少对一些人来说) 被忽略。

信号名称是通过包含头文件 signal.h 来定义的,他们均以 SIG 开头,下表列出常见信号。

如果一个进程接收到其中一个信号而没有先安排捕获它,该进程将立即终止。通常会创建一个核心转储文件。这个文件称为 core,放在当前目录中,是进程的映像,在调试中很有用。

附加信号包括下表中的信号。

SIGCHLD 对于管理子进程很有用。默认情况下它会被忽略。其余的信号会导致接收它们的进程停止,SIGCONT 除外,它会导致进程恢复。它们被 shell 程序用于作业控制,很少被用户程序使用。

我们稍后会更详细地讨论第一组信号。现在,只要知道如果 shell 和终端驱动程序配置正常,在键盘上输入中断字符 (通常是Ctrl+C) 将导致 SIGINT 信号被发送到前台进程,即当前正在运行的程序就足够了。这将导致程序终止,除非它已安排捕捉信号。

如果要向当前前台任务以外的进程发送信号,可以使用 kill 命令。它接受一个可选的信号或名称,以及要将信号发送到的 PID (通常使用ps命令找到)。例如,要向运行在另一个PID为 512 的终端上的shell发送“挂起”信号,可以使用该命令:

$ kill –HUP 512

kill 命令的一个有用的变体是 killall,它允许向运行指定命令的所有进程发送信号。并非所有版本的 UNIX 都支持它,但 Linux 通常支持。当我们不知道 PID 时,或者当我们想向执行相同命令的多个不同进程发送信号时,这非常有用。一个常见的用法是告诉 inetd 程序重新读取它的配置选项。为此,我们可以使用命令:

$ killall –HUP inetd

程序可以使用信号库函数处理信号。

这个相当复杂的声明说明,signal 是一个接受两个形参的函数,sig 和 func。要捕获或忽略的信号作为参数 sig 给出。接收到指定信号时要调用的函数以 func 的形式给出。此函数必须接受单个int参数 (接收到的信号) ,且类型为 void。信号函数本身返回一个相同类型的函数,这是为处理该信号而设置的函数的前一个值,或者是以下两个特殊值之一:

举个例子就能说明问题。在下面的程序中,编写一个程序 ctrlc.c,它对键入Ctrl+C 做出反应,打印适当的消息而不是终止。第二次按 Ctrl+C 将结束程序。

1、Signal Handling(ctrlc.c)

函数 ouch 对传入参数 sig 中的信号作出反应,当信号出现时将调用这个函数。它打印一条消息,然后将 SIGINT 的信号处理 (默认情况下,通过键入 Ctrl+C 生成) 重置为默认行为。

main 函数必须拦截当我们键入 Ctrl+C 时生成的 SIGINT 信号。在其余的时间里,它只是处于一个无限循环中,每秒打印一条消息。

#include<signal.h>
#include<stdio.h>
#include<unistd.h>

void ouch(int sig)
{
    printf("OUCH! - I got signal %d\n",sig);
    (void) signal(SIGINT,SIG_DFL);
}

int main()
{
    (void) signal(SIGINT,SIG_DFL);

    while(1){
        printf("Hello World!\n");
        sleep(1);
    }
    //exit(0);
}

第一次输入 Ctrl+C (如下面的输出中显示为 ^C)  会导致程序做出反应,然后继续。当你再次键入Ctrl+C时,程序将结束,因为SIGINT的行为已经返回到导致程序退出的默认行为。

从这个示例中可以看到,信号处理函数接受一个整数参数,即导致调用函数的信号。如果相同的函数用于处理多个信号,这将非常有用。在这里打印出 SIGINT 的值,在这个系统中它的值恰好是 2。你不应该依赖于传统的数值来获取信号;在新程序中始终使用信号名称。

从信号处理程序内部调用所有函数 (如 printf ) 是不安全的。一种有用的技术是使用信号处理程序设置一个标志,然后从主程序中检查该标志,并在需要时打印一条消息。最后,你将发现可以在信号处理程序内部安全地执行的调用列表。

How It Works:

当你通过键入 Ctrl+C 给出 SIGINT 信号时,程序安排函数 ouch 被调用。在中断函数 ouch 完成后,程序继续执行,但信号动作被恢复到默认值。(不同版本的 UNIX,特别是源自 Berkeley UNIX 的 UNIX,在历史上具有微妙的不同信号行为。如果你想在一个信号发生后恢复它的默认动作,最好是专门这样编码。)当它接收到第二个 SIGINT 信号时,程序采取默认操作,即终止程序。

如果希望保留信号处理程序并继续对 Ctrl+C 作出反应,则需要通过再次调用信号来重新建立它。这将导致从中断函数开始到重新建立信号处理程序之前的一小段时间内没有处理信号。有可能在这个时候接收到第二个信号并违背人的意愿终止程序。

我们不建议使用信号接口来捕获信号。我们在这里包含它,因为我们会在许多较老的程序中发现它。稍后我们将看到 sigaction,这是一个定义更清晰、更可靠的接口,我们应该在所有新程序中使用它。

如果有,signal 函数返回指定信号的信号处理程序的前一个值,否则返回 SIG_ERR,在这种情况下,errno 将被设置为正数。如果指定了无效的信号,或者试图处理无法捕获或忽略的信号 (如SIGKILL) ,则 errno 将设置为 EINVAL。

2、Sending Signals

一个进程可以通过调用 kill 向其他进程 (包括它自己) 发送信号。如果程序没有发送信号的权限,调用将失败,通常是因为目标进程属于另一个用户。这是等价于同名 shell 命令的程序。

kill 函数将指定的信号 sig 发送给 pid 指定标识符的进程。成功时返回 0。要发送一个信号,发送进程必须有这样做的权限。通常,这意味着两个进程必须具有相同的用户 ID (也就是说,我们只能向自己的一个进程发送信号,尽管超级用户可以向任何进程发送信号)。

kill 将失败,返回 -1,如果给出的信号不是有效的 ( errno 设置为 EINVAL ),如果它没有权限 (EPERM),或者如果指定的进程不存在 (ESRCH),则设置 errno。

信号为你提供了一个有用的闹钟设施。进程可以使用警报函数调用在未来的某个时间调度 SIGALRM 信号。

警告调用以秒为单位调度 SIGALRM 信号的发送。事实上,由于处理延迟和调度的不确定性,警报将在那之后不久交付。值 0 将取消任何未完成的报警请求。在接收到该信号之前调用该警告将导致该 alarm 重新调度。每个进程只能有一个未处理的 alarm。alarm 返回任何未完成的警报调用将被发送之前的剩余秒数,如果调用失败则返回 -1。

要了解 alarm 是如何工作的,可以使用 fork、sleep 和 signal 来模拟它的效果。一个程序可以启动一个新的进程,唯一的目的是在稍后的某个时间发送一个信号。

(1)alarm.c

在 alarm.c 中,第一个函数 ding 模拟闹钟。

#include<signal.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

static int alarm_fired=0;

void ding(int sig)
{
    alarm_fired=1;
}

/*In main, you tell the child process to wait for five seconds before sending a SIGALRM signal to its parent.*/
int main()
{
    pid_t pid;
    printf("alarm application starting\n");

    pid=fork();
    switch(pid){
        case -1:
            perror("fork failed");
            exit(1);
        case 0:
            sleep(5);
            kill(getppid(),SIGALRM);
            exit(0);
    }

    /*The parent process arranges to catch SIGALRM with a call to signal and then waits for the inevitable.*/

    /* if we get here we are the parent process */
    printf("waiting for alarm to go off\n");
    (void) signal(SIGALRM,ding);

    pause();
    if(alarm_fired)
        printf("Ding!\n");

    printf("done\n");
    exit(0);
}

这个程序引入了一个新函数 pause,它只是使程序暂停执行,直到出现信号。当它接收到信号时,运行任何已建立的处理程序,并照常继续执行。它被声明为:

并返回 -1 (如果下一个接收到的信号没有导致程序终止),当被信号中断时,errno 设置为 EINTR。更常见的是在等待信号时使用 sigsuspend。

How It Works:

闹钟模拟程序通过 fork 启动一个新的进程。这个子进程休眠 5 秒钟,然后向它的父进程发送一个 SIGALRM 。父进程安排捕获 SIGALRM,然后暂停直到接收到信号。不要在信号处理程序中直接调用 printf,相反,我们可以设置一个标志,然后在之后检查该标志。

使用信号和暂停执行是 Linux 编程的一个重要部分。这意味着程序不一定要一直运行。它可以等待事件发生,而不是在循环中不断地检查事件是否发生。这在多用户环境中尤其重要,因为在多用户环境中,进程共享一个处理器,这种繁忙等待对系统性能有很大的影响。关于信号的一个特殊问题是,我们永远不知道 “如果在系统调用中间出现一个信号会发生什么?” (答案是相当令人不满意的“视情况而定”) 通常,我们只需要担心“慢”的系统调用,例如从终端读取,如果在等待时出现信号,系统调用将返回一个错误。如果开始在程序中使用信号,则需要注意,如果信号导致在添加信号处理之前可能没有考虑到的错误条件,那么一些系统调用可能会失败。

我们必须仔细编写我们的信号,因为在使用它们的程序中可能会出现许多“竞态条件”。例如,如果我们打算调用 pause 来等待一个信号,而该信号在调用 pause 之前发生,那么程序可能会无限期地等待一个不会发生的事件。这些竞争条件,关键的时间问题,让许多新手程序员感到困惑。我们最好总是非常仔细地检查信号代码。

(2)A Robust Signals Interface

我们已经深入讨论了使用 signal 和 friends 引发和捕获信号,因为它们在较老的 UNIX 程序中非常常见。然而,X/Open 和 UNIX 规范为更健壮的信号推荐了一个更新的编程接口:sigaction。

sigaction 结构,用于定义接收到 sig 指定的信号时要采取的动作,在头文件 signal.h 中定义,且至少具有以下成员: 

sigaction 函数的作用是设置与信号 sig 相关联的动作。将前一个信号动作写入它所引用的位置。如果 act 为空,这就是 sigaction 所做的一切。如果 act 不为空,则为指定信号设置动作。

与 signal 一样,sigaction 如果成功返回 0,否则返回 -1。如果指定的信号无效,或者试图捕获或忽略无法捕获或忽略的信号,则错误变量 errno 将被设置为 EINVAL。

在参数 act 所指向的 sigaction 结构中,sa_handler 是一个指针,指向接收到信号 sig 时调用的函数。这很像我们前面看到的传递给 signal 的函数 func。可以在 sa_handler 字段中使用特殊值 SIG_IGN 和 SIG_DFL,分别表示要忽略信号或将动作恢复为默认值。

sa_mask 字段指定在调用 sa_handler 函数之前要添加到进程的信号掩码中的一组信号。这些是被阻塞的信号集,不会被传递到进程。这防止了我们前面看到的在处理程序运行完成之前就接收到信号的情况。使用 sa 掩码字段可以消除这种竞态条件。

但是,sigaction 设置的处理程序捕获的信号在默认情况下不会重置,如果我们想获得前面看到的 signal 的行为,则必须将 sa_flags 字段设置为包含值 SA_RESETHAND。在更详细地研究 sigaction 之前,让我们用 sigaction 代替 signal 重写程序 ctrlc.c。

(3)ctrlc2.c

进行以下更改,以便 sigaction 拦截SIGINT。调用新程序ctrlc2.c。

#include<signal.h>
#include<stdio.h>
#include<unistd.h>

void ouch(int sig)
{
    printf("OUCH! - I got signal %d\n",sig);
}

int main()
{
    struct sigaction act;

    act.sa_handler=ouch;
    sigemptyset(&act.sa_mask);
    act.sa_flags=0;

    sigaction(SIGINT,&act,0);

    (void) signal(SIGINT,SIG_DFL);

    while(1){
        printf("Hello World!\n");
        sleep(1);
    }
    //exit(0);
}

当运行这个版本的程序时,当键入 Ctrl+C 时总是会收到一条消息,因为 sigaction 会重复处理 SIGINT 。要终止程序,必须键入 Ctrl+\,默认情况下会生成SIGQUIT信号。

但实际上,运行的时候按 Ctrl+C 可能也会停止。

How It Works: 

该程序调用 sigaction 而不是 signal 来将 Ctrl+C (SIGINT) 的信号处理程序设置为函数 ouch。它首先必须设置一个 sigaction 结构,该结构包含处理程序、信号掩码和标志。在这种情况下,你不需要任何标志,并且用新函数创建了一个空信号掩码 sigemptyset。

运行此程序后,你可能会发现已经创建了一个核心转储 (在一个名为 core 的文件中)。你可以安全地删除它。

3、Signal Sets

头文件 signal.h 定义了 sigset_t 类型和用于操作信号集的函数。这些集合用于 sigaction 和其他函数,以在接收到信号时修改进程行为。

这些函数执行其名称所建议的操作。sigemptyset 将信号集初始化为空。sigfillset 初始化一个信号集以包含所有已定义的信号。sigaddset 和 sigdelset 从信号集中添加和删除指定的信号 (signo)。如果成功,它们都返回 0,如果 errno 设置为 error,则返回 -1。如果指定的信号无效,唯一定义的错误是 EINVAL。

sigismember 函数确定给定的信号是否是信号集的成员。如果信号是集合的成员,则返回 1;如果不是,则返回0;如果信号无效,则返回 -1,errno 设置为 EINVAL。

通过调用函数 sigprocmask 来设置或检查进程信号掩码。此信号掩码是当前被阻塞的信号集,因此当前进程不会接收到这些信号。

sigprocmask 可以根据 how 参数以多种方式更改进程信号掩码。如果信号掩码不为空,则在参数集中传递新的信号掩码值,以及前一个信号掩码将被写入信号集。

how参数可以是以下参数之一:

如果 set 参数是空指针,how 的值不会被使用,调用的唯一目的是将当前信号掩码的值取到 oset中。

如果它成功完成,sigprocmask 返回 0,如果 how 参数无效,则返回 -1,在这种情况下,errno 将被设置为 EINVAL。

如果一个信号被进程阻塞,它将不会被传递,而是保持挂起状态。程序可以通过调用 sigpending 函数来确定哪些被阻塞的信号正在等待。

它将一组被阻塞的信号写入 set 所指向的信号集中。如果成功,则返回 0,否则返回 -1,并设置 errno 以指示错误。当程序需要处理信号和控制何时调用处理函数时,此函数非常有用。

进程可以通过调用 sigsuspend 暂停执行,直到传递一组信号中的一个为止。这是前面提到的 pause 函数的一种更一般的形式。

sigsuspend 函数用 sigmask 给出的信号集替换进程信号掩码,然后暂停执行。它将在信号处理函数执行后恢复。如果接收到的信号终止程序,sigsuspend 将永远不会返回。如果接收到的信号没有终止程序,sigsuspend 返回 -1, errno 设置为 EINTR。

(1)sigaction Flags

sigaction 中使用的 sigaction 结构的 sa_flags 字段可以包含下表中所示的值,以修改信号行为:

SA_RESETHAND 标志可用于在捕获信号时自动清除信号函数,如前所述。 

程序使用的许多系统调用都是可中断的;也就是说,当它们接收到一个信号时,它们将返回一个错误,errno 将被设置为 EINTR,以指示由于信号而返回的函数。这种行为需要使用信号的应用程序格外注意。如果在 sigaction 调用中的 sa_flags 字段中设置了 SA_RESTART,那么在执行信号处理函数后,可能会被信号中断的函数将被重新启动。

通常,当一个信号处理函数正在执行时,接收到的信号被添加到处理函数期间的进程信号掩码中。这将防止后续出现相同的信号,从而导致信号处理函数再次运行。如果函数不是可重入的,那么在它完成处理第一个信号之前,让另一个信号调用它可能会导致问题。但是,如果设置了 SA_NODEFER 标志,则在接收到该信号时不会更改信号掩码。

信号处理函数可能在中间被中断,然后被其他函数再次调用。当你回到第一个电话时,它仍然正确地运行是至关重要的。它不仅是递归的(调用自身),而且是可重入的(可以毫无问题地再次输入和执行)。内核中同时处理多个设备的中断服务例程需要是可重入的,因为在执行相同的代码时,一个高优先级的中断可能会“进入”。

在信号处理程序内部调用是安全的函数,即 X/Open 规范所保证的函数是可重入的,还是本身不发出信号,都在下表中列出。

所有未在下表中列出的功能都应被认为对信号不安全

 ​

(2)Common Signal Reference

接下来我们列出 Linux 和 UNIX 程序通常需要的信号及其默认行为。

下表中信号的默认操作是异常终止进程,其结果为 _exit (类似于 exit,但在返回内核之前不执行清除操作)。但是,该状态可用于等待,waitpid 表示由指定的信号异常终止。

缺省情况下,下一个表的信号也会导致异常终止。此外,可能会发生与实现相关的操作,如创建核心文件。

默认情况下,进程在接收到下表中的一个信号时被挂起。

SIGCONT 将重新启动已停止的进程,如果被未停止的进程接收,则忽略 SIGCONT。SIGCHLD 标志在默认情况下被忽略。 

小结:

已经了解了进程是 Linux 操作系统的一个基本组成部分。已经了解了如何启动、终止和查看它们,以及如何使用它们解决编程问题。我们还了解了信号和事件,这些事件可用于控制正在运行的程序的操作。所有Linux进程 (包括init) 都使用对任何程序员可用的相同系统调用集。

以上,进程与信号(三)

祝好

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

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

相关文章

小学生python游戏编程arcade----单词对错检测及记录写入excel中

小学生python游戏编程arcade----单词对错检测及记录写入excel中前言单词对错检测及记录写入excel中1、excel读取修改1.1 excel读取1.2 修改用到的库1.3 获取Excel表格名称的三种方式1.4 excel格式问题excel文件保存2.1 保存函数2.2 实验2.3 游戏中调用修改2.4 升级时保存字典内…

SuperMap GIS管线数据优化

一、优化目的 城市管网数据错综复杂&#xff0c;未经优化处理的数据在加载过程中可能会出现显示效果差&#xff0c;浏览效率低的情况&#xff0c;特别是在浏览器端&#xff0c;受文件请求量&#xff0c;网络带宽、硬件性能等方面的影响&#xff0c;未经优化的管线数据显示可能不…

5个高清图片素材网站,无水印,免费商用。

网上找的图片素材清晰度不够&#xff0c;版权不明确怎么办。看看这几个可商用图片素材网站&#xff0c;解决你的所有图片需求&#xff0c;高清无水印、下载无限制、免费可商用&#xff0c;赶紧马住&#xff01; 1、菜鸟图库 https://www.sucai999.com/pic.html?vNTYxMjky 网站…

【学习笔记54】运动函数的分析

一、运动函数的基本实现 运动函数是我们自己封装的一个函数。作用是将css样式的改变不是一次性完成&#xff0c;是逐步完成执行效果&#xff0c;看上去像是动画/运动完成的css样式改变。实际项目中框架等都有自己的运动函数我们目前封装一个简单的兼容多属性的运动函数。 1、HT…

回溯法(Java)

回溯法&#xff08;Java&#xff09; 文章目录回溯法&#xff08;Java&#xff09;1、引言2、回溯法2.1 定义2.2 使用场合2.3 基本做法2.4 具体做法2.5 常见例子3、比较4、 问题的解空间4.1 介绍4.2 解空间&#xff08;Solution Space&#xff09;4.3 举例5、基本思想5.1 基本步…

Starday跨境电商平台靠“三快”取胜

入驻快、支付快、物流快 在这个瞬息万变的互联网世界&#xff0c;追求“快”已经成为各行各业的共识&#xff0c;而对于一个因互联网发展而诞生的新兴行业——跨境电商行业&#xff0c;“快”就是跨境电商行业的第一生产力&#xff0c;要想在众多的跨境电商行业中成功出圈&…

【allegro 17.4软件操作保姆级教程六】布线操作基础之一

目录 1.1走线和修线 1.2 Copy操作 1.3 change操作 1.4 删除操作 1.5 Z-copy操作 1.6 Sub-drawing操作 1.1走线和修线 这两个操作是布线时用的最多最基础的操作。如下图&#xff0c;左边是走线命令&#xff08;add connect&#xff09;&#xff0c;右边是修线命令&#x…

外卖项目(项目优化3)12---前后端分离开发

目录 问题描述&#xff1a;184 一、前后端分离开发 185 1.1介绍 185 1.2开发流程 1.3前端技术栈 二、YAPI 186 2.1介绍 2.2使用方式 三、Swagger 187 3.1介绍 3.2使用方式&#xff08;步骤&#xff09; 3.3Swagger---常用注解 188 四、项目部署 189 4.1部署架构…

虹科分享 | 网络流量监控 | 使用 ntopng 收件人和端点进行灵活的警报处理

在之前&#xff0c;ntopng引擎对所有警报的配置是单一的&#xff1a;进入偏好页面并指定警报的发送地点。但这是不理想的&#xff0c;原因有很多&#xff1a;包括不可能在不同的渠道向不同的收件人发送警报&#xff0c;或有选择地决定何时发送警报。 出于这个原因&#xff0c;…

【教材】20022/11/28[指针] 指针数组

一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都存放一个地址,相当于一个指针变量。下面定义一个指针数组:int *p[4] 注意不要写成int &#xff08;*p&#xff09;[4]. 可以分别定义一些字符串,然后用指针数组中的元素分别指向各字符串,在n…

二手闲置物品交易数据快照

近年来&#xff0c;中国社会消费品零售总额不断增长&#xff0c;2019 年1-4 月,消费品零售总额达到128375.8 亿元&#xff0c;同比增长8%。消费者购买力的增强和电商行业的发展&#xff0c;给购买行为提供便利条件&#xff0c;消费者冲动消费后的闲置产品&#xff0c;给二手交易…

《前端》JavaScript总结

文章目录js的使用方法变量与运算符let 与 const变量类型运算符输入与输出输入输出格式化字符串判断语句循环语句for循环while循环do...while循环对象数组访问数组中的元素数组常用属性和函数函数类定义继承静态方法静态变量事件鼠标键盘表单窗口js的使用方法 **使用方式&#…

网络安全工程师必备证书有哪些?

网络环境之间的竞争&#xff0c;归根到底优秀人才之间的竞争。 在2022年网络安全周上&#xff0c;《网络安全人才实战能力白皮书》正式公布。资料显示&#xff0c;到2027年&#xff0c;我国网络安全人员缺口将达327万&#xff0c;而高校人才培养经营规模仅是3万/年。 那样&am…

上半年亏损之下,卫龙第三次冲刺港股IPO

据港交所文件显示&#xff0c;今年6月27日卫龙美味通过港交所上市聆听&#xff0c;11月24日&#xff0c;卫龙更新了聆听后资料集。若此次上市成功&#xff0c;卫龙将成为港股乃至国内辣条第一股。 此前&#xff0c;卫龙已经两度申请了赴港IPO&#xff0c;但都功败垂成&#xff…

看看咱是如何用MATLAB白嫖遥遥领先于同行的神仙级翻译工具 — DeepL

伙伴们不用惊讶&#xff0c;标题仅仅是借用余大嘴的专用修饰语“遥遥领先于同行”而已&#xff0c;但讲DeepL翻译器遥遥领先于同行也不为过&#xff0c;下图是官方给出的采用盲测的方式与其他同类产品的对比图&#xff0c;这应该不是吹牛X&#xff1a; 如此优秀的翻译神器&…

免改造密码方案入选工信部“首届全国商用密码应用优秀案例”

2022年8月18日&#xff0c;“首届全国商用密码应用优秀案例”评选结果重磅揭晓&#xff0c;炼石网络与陕西移动联合打造的“面向重要数据与个人信息保护的商用密码解决方案”&#xff0c;凭借创新性及技术优势&#xff0c;从102个案例中脱颖而出、成功入选&#xff0c;并被收录…

yolov4训练数据: cuda和cudnn的安装

近期再搞openvinoYolov4目标检测&#xff0c;记录一下cuda和cudnn的安装笔记。 mirrors / alexeyab / darknet GitCode 1.cuda的安装 cuDNN Archive | NVIDIA Developer wget https://developer.download.nvidia.com/compute/cuda/10.2/Prod/local_installers/cuda_10.2.89_…

【SVM时序预测】基于matlab鲸鱼算法优化支持向量机SVM时序数据预测【含Matlab源码 2250期】

⛄一、鲸鱼算法优化支持向量机SVM 1 鲸鱼优化算法 WOA是由Mirjalili和Lewis在2016年提出的一种较为新颖的元启发式群体智能优化算法&#xff0c;该算法模仿座头鲸的“螺旋气泡网”捕食策略&#xff0c;如图1所示。 图1 座头鲸“螺旋起泡网”捕食策略 WOA算法寻优步骤如下。 步…

详解企业财务数字化转型路径|推荐收藏

许多企业在推动各大业务部门进行数字化转型时&#xff0c;往往会忽略财务部门。然而&#xff0c;作为掌握公司核心资源与数据和推动企业信息化建设的部门&#xff0c;财务部门也应成为企业数字化转型的重要突破口。 财务数字化转型是运用信息技术等手段对财务数据进行统计、记录…

【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)

需要源码请点赞关注收藏后评论区留言私信~~~ 一、OpenGL ES简介 虽然OpenGL的三维制图功能非常强大&#xff0c;但是它主要为计算机设计的&#xff0c;对于嵌入式设备和移动端设备来说显得比较臃肿&#xff0c;所以业界又设计了专供嵌入式设备的OpenGL ES 它相当于OpenGL的精简…