当前位置: 首页 > news >正文

零基础Linux_10(进程)进程终止(main函数的返回值)+进程等待

目录

1. 进程终止

1.1 main函数的返回值

1.2 进程退出码和错误码

1.3 进程终止的常见方法

2. 进程等待

2.1 进程等待的原因

2.2 wait 函数

2.3 waitpid 函数

2.4 int* status参数

2.5 int options非阻塞等待

本篇完。


1. 进程终止

进程终止指的就是程序执行结束了,进程终止退出的场景有三种:

  • 代码运行完毕且结果正确
  • 代码运行完毕但结果不正确
  • 代码异常终止

1.1 main函数的返回值

刚开始是如何学习 C/C++ 的呢?

#include <stdio.h>int main()
{printf("hello world!\n");return 0;
}

C/C++ 的时侯,main函数就是所谓的 入口函数

大家对 hello world! 再熟悉不过了,但是不知道大家是否关注过这个 return ?

下面我们思考两个问题:

① 这个return 0究竟给谁return?

 为什么是0?其它值不行吗?

上面提到:进程终止退出的场景有三种:

  • 代码运行完毕且结果正确
  • 代码运行完毕但结果不正确
  • 代码异常终止

返回值为 0,表示进程代码跑完。结果是否正确?-> 我们用 0 表示正确,非 0 表示不正确。(因为正确的原因只有一种,不正确的原因确有很多种)

所以,写main函数无脑返回 0 是不正确的,准确来说应该要给不同的值。

1.2 进程退出码和错误码

0 表示正确,非 0 表示不正确。那么这么多非0,我们要返回那个值?

我们把 main 函数的返回值称之为 进程退出码

进程退出码是非常重要的,进程退出码表征了进程推出的信息,它是要给父进程读取的。

我们通过内置命令echo,我们让bash自己执行内部的函数来打印:(这里创建linux_10目录)

 

  编译运行后输入几次echo $?

 

 这里之所以会第一次执行echo $?得到 7,后面再输入得到 0,原因如下:

$? 表示在 bash 中,最近一次执行完毕时,对应进程的退出码,这里第一次我们运行test,退出码是7,echo $?,也是一个进程,这里它的退出码是0

所以我们来试试使用 ls 指令后输入 echo $?

 

  这里 ls 中打开一个没有的文件,退出码是2?为什么这么设计呢?

我们先看看错误码:

首先,失败的非零值是可以自定义的,我们可以看看系统对于不同数字默认的 错误码 是什么含义。C 语言当中有个的 string.h 中有一个 strerror 接口,是最经典的、将错误码表述打印出来的接口,我们可以在写个代码去把这些错误码给打印出来:(这里有133个,往后面打都是不知道的错误了)

 

 

 

0是成功, 1表示权限不允许,2表示找不到文件或目录......输出错误原因定义归纳整理如下:(这里先不用记,记也记不下来,可以看看前十个)

#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */
#define ENOSYS 38 /* Function not implemented */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Too many symbolic links encountered */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */
#define EDEADLOCK EDEADLK
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ 84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define EADDRINUSE 98 /* Address already in use */
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
#define ENETDOWN 100 /* Network is down */
#define ENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102 /* Network dropped connection because of reset */
#define ECONNABORTED 103 /* Software caused connection abort */
#define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105 /* No buffer space available */
#define EISCONN 106 /* Transport endpoint is already connected */
#define ENOTCONN 107 /* Transport endpoint is not connected */
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
#define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */
#define EHOSTDOWN 112 /* Host is down */
#define EHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /* Operation already in progress */
#define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE 116 /* Stale NFS file handle */
#define EUCLEAN 117 /* Structure needs cleaning */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */
#define EDQUOT 122 /* Quota exceeded */
#define ENOMEDIUM 123 /* Nomedium found */
#define EMEDIUMTYEP 124 /*Wrongmedium found */
#define ECANCELED 125 /* Operation Canceled */
#define ENOKEY 126 /* Required key not available */
#define EKEYEXPIRED 127 /* Key has expired */
#define EKEYREVOKED 128 /* Key has been revoked */
#define EKEYREJECTED 129 /* Key was rejected by service */
#define EOWNERDEAD 130 /* Owner died */
#define ENOTRECOVERABLE 131 /* State not recoverable */
#define ERFKILL 132 /* Operation not possible due to RF-kill */
#define EHWPOISON 133 /* Memory page has hardware error */

错误码退出码可以对应不同的错误原因,方便我们定位问题出在哪里。

1.3 进程终止的常见方法

进程终止的常见方法:在main函数return     调用 exit     ③ 调用 _exit

两个QA:

1. 在main函数return(为什么其他函数不行)?:

只有在 main 函数调 return 才叫做 进程退出,其他函数调 return 叫做 函数返回。

2. 为什么在的代码任意地点中,调用 exit  都可以做到进程退出。

exit:该函数想必大家并不陌生,exit  并不是一个系统调用,而是用C语言写的,头文件是stdlib.h

我们来用一下这个 exit 函数:

编译运行:

 在 main 函数调了 func 函数,进去打印后执行了 exit,最后进程没有返回直接在函数内部直接终止进程,这就叫调 exit 直接终止进程。此时我们 echo $? 得到的结果是 7。

exit 当然也是可以在 main 函数中使用的,这里就不演示了。如果你以后想终止一个进程,只需要在任意地点调用 exit 去 "代表" 进程退出。

下面我们再来讲解一下 _exit 函数,_exit 也是一个系统调用,也是可以用来终止进程的。

exit 和 _exit 是调用和被调用的关系,exit 是调用了 _exit 的。

 区别:_exit()是系统调用,而exit()是库函数。exit 会清理缓冲区,关闭流等操作,而 _exit 什么都不干,直接终止:

结合以前缓冲区的知识,这里没了\n,用_exit 

换成exit:

据此,我们以后直接用exit就行了。

2. 进程等待

进程等待是进程的一种状态,是父进程等待子进程退出时的一个过程。

2.1 进程等待的原因

子进程退出,父进程不管子进程,子进程就要处于僵尸状态,从而导致内存泄漏。

所以我们必须让其从 Z 状态变为 X 状态,进而允许操作系统能去释放它。

上面我们讲的实际上就是我们需要进程等待的一个原因 —— 解决内存泄露问题 

然而不仅仅这一个原因,我们还需要进程等待来 获取子进程的退出状态 。

获取子进程的退出状态是否需要将曾经子进程的退出信息保存起来,然后被恢复、读取呢?

这和我们刚才讲的进程退出有着很大的关系,我们知道了进程退出是有退出码的。

我们需要让子进程退出时它的 return 结果或者 exit 的结果是需要被父进程读到的。

父进程创建了子进程,是要让子进程办事的,那么子进程把任务完成的怎么样了父进程需要关心吗?如果需要,如何得知?如果不需要,该怎么处理?

父进程通过进程等待的方式,回收子进程资源,获得子进程退出信息。

需要进程等待的原因:① 解决内存泄露问题     ② 获取子进程的退出状态

进程终止退出的场景有三种:(进程等待就是依照下面三种问题进程处理)

  • 代码运行完毕且结果正确
  • 代码运行完毕但结果不正确
  • 代码异常终止

2.2 wait 函数

我们先来介绍一下 wait 函数。第一种方式,就是让父进程调用 wait 即可。

wait() 可以解决回收子进程 Z 状态,让子进程进入 X 状态。

#include <sys/types.h>
#include <sys/wait.h>pid_t wait(int* status);

返回值:成功返回被等待子进程pid,失败返回 - 1。
参数int* status:输出型参数,获取子进程退出状态, 不关心则可以设置成为NULL

验证:调用 wait 函数让父进程等待子进程:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{pid_t id = fork();if (id == 0){int cnt = 5;while (cnt--) {printf("我是子进程%d,我在运行,Pid: %d\n", cnt,getpid());sleep(1);}exit(0); // 退出子进程}else{printf("我是父进程: 我在等待子进程,pid: %d,\n", getpid());sleep(7);pid_t ret = wait(NULL);  // 阻塞式等待,暂且将status参数设置为NULLif (ret < 0){printf("等待失败!\n");}else {printf("等待成功!\n");   // 此时 Z → X}while (1) // 阻塞式等待不会走到这{printf("我是父进程,我在运行,Pid: %d\n", getpid());sleep(1);}}return 0;
}

为了观察进程状态,在右边开一会话,写一段监控脚本(注意这里grep test是我生成的可执行文件名字test),做到每隔一秒就监控一下进程,右边输入:

while :; do ps ajx | head -1 && ps ajx | grep test| grep -v grep; echo "-------------------------------------------"; sleep 1; done

左边编译运行:

 右边看到了两秒的僵尸进程Z:

 成功验证了父进程等待了子进程。

通过 wait() 的方案,我们可以解决回收子进程的 ​​​​​​Z 状态,让子进程进入 X 状态。

2.3 waitpid 函数

刚才讲的 wait 其功能比较简单,在进程等待时用的更多的是 waitpid

waitpid 可以把 wait 完全包含,wait 是 waitpid 的一个子功能。

wait/waitpid 都可以回收子进程的僵尸状态。

#include <sys/types.h>
#include <sys/wait.h>pid_t waitpid(pid_t pid, int* status, int options);

返回值:

如果 pid_t > 0:等待子进程成功,返回值就是子进程的 pid;
如果 pid_t < 0:等待失败。


在非阻塞等待中,没有等待失败,如果 pid_t  = 0:如果子进程没有终止,那么返回0,如果终止且等待成功,返回子进程的pid值。


参数 pid_t pid:

设置参数 pid > 0:是几,就代表等待哪一个子进程,比如 pid=1234,指定等待。
设置参数 pid = -1:等待任意进程。(wait的就是等待任意进程)

参数int* status:和wait一样,输出型参数,获取子进程退出状态, 不关心则可以设置成为NULL(后面详讲)


对于参数 int options:0为阻塞等待(wait的就是阻塞等待),1为非阻塞等待,

非阻塞等待一般传WNOHANG(这个宏定义就直接定义为了1,Wait NO HANG夯住了(停了))

在使用wait的代码的基础上,参数这样改就和wait一样了:

 编译运行+监控:

while :; do ps ajx | head -1 && ps ajx | grep test| grep -v grep; echo "-------------------------------------------"; sleep 1; done

2.4 int* status参数

wait 和 waitpid,都有这个 status 参数,我们刚才演示 wait 的时候传的是 NULL,

如果传递 NULL,则表示不关心子进程的退出状态信息。否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。

该参数是一个 输出型参数 (即通过调用该函数,从函数内部拿出来特定的数据)。

并且,status 参数是由操作系统填充的,是一个整数,该整数就是下面我们要详细研究的。

它虽然是一个 int 型整数,但不能简单的当作整形来看待,

可以当作位图来看待,具体细节如下图(只研究status低16比特 位):

core dump 指的是 核心转储,也可以称之为 "吐核"。

它是操作系统在进程收到某些信号而终止运行时,将此时进程地址空间的内容以及有关进程状态的其他信息写出的一个磁盘文件。目前只需要知道,该信息是用于调试的。

现在上面的代码改一点,使用 waitpid 的 int* status参数,

验证: 通过提取 status 次低8位,拿到子进程的退出码:

位运算复习链接:C语言初阶⑥(操作符详解)编程作业(算数转换)__GR的博客-CSDN博客

 status 右移八位再按位与上 0xFF,即 (status >>8)&0xFF ,就可以提取到 status 的次低八位(这里应该得到子进程里exit(77)的77),编译运行:

 

验证: 通过提取 status 最低7位,得到子进程的退出信号:

status 的低八位用于表示处理异常的地方,其中有 1 位是 core dump,最上面简单知道就行了。除去 core dump,剩余七位用于进程中的退出信号,这就是 最低七位。

进程退出,如果异常退出,是因为这个进程收到了特定的信号。

我们虽然还没有开始讲解信号,但是我们前几张就介绍了 kill -9 这样的杀进程操作。

这个 -9 我们当时说了,就是一个信号,发送该信号也确实可以终止进程。

刚才我们讲的 wait/waitpid 和次低八位的时侯,都是关于进程的 正常退出。

如果进程 异常退出 呢?我们来模拟一下进程的异常退出(就是使用kill -9)。

代码演示:模拟异常退出的情况,这里把子进程改成死循环,父进程一直等。

此时我们讲父进程打印的消息再增添一个 "退出信号",也就是提取 status 的最低7位,我们想让低7位保留,高25位清0,让 status 按位与上 0x7F 即可

  编译运行+监控:

while :; do ps ajx | head -1 && ps ajx | grep test| grep -v grep; echo "-------------------------------------------"; sleep 1; done

 一直在运行,不终止,再开一个窗口,输入kill -9信号终止子进程:

这里一直阻塞式等待的父进程等待到子进程退出后也开始运行,并且成功打印退出信号

代码跑完结果是什么已经不重要了,我们最关心的是因为什么原因退出的。

当进程收到信号时,就代表进程异常了。进程程出,如果是异常退出,是因为该进程收到了特定的信号。其实除了 9 号信号还有很多信号,输入 kill -l 就可以查看这些:

比如遇到的除零警告:

 编译运行:

while :; do ps ajx | head -1 && ps ajx | grep test| grep -v grep; echo "-------------------------------------------"; sleep 1; done

这时成功打印 8 号退出信号:SIGFPE(Float Pointer Error)

实际上,我们在编程学习中遇到的程序崩溃,程序一崩溃程序就退出了,今天在我们操作系统的角度来看,这就是进程终止。其实是因为错误而导致了软硬件错误,操作系统通过发送信号的方式把进程杀掉了。至于操作系统凭什么可以终止, 又是怎么发信号的?又是如何终止的?详细的过程是什么?这些问题后面会讲。

打印子进程ID和退出信号还要进行位运算,这么麻烦是不是有点挫?所以Linux 已经给我们提供了一些宏供我们直接调用。它们是 WEXITSTATUS 和 WIFEXITED,实现就是和上面位运算一样的

WIFEXITED(status): 若为正常终止子进程返回的状态,则为真(查看进程是否是正常退出)
(w是wait,w if exit )
WEXITSTATUS(status): WIFEXITED 非零,提取子进程退出码(查看进程的退出码)
(w是wait,w exit status)

我们先思考一个问题:

一个进程退出时,可以拿到退出码和推出信号,我们先看谁?

一旦程序发现异常,我们只关心退出信号,退出码没有任何意义。

所以,我们先关注退出信号,如果有异常了我们再去关注退出码。

代码演示:

2.5 int options非阻塞等待

aitpid的第三个参数就是用了决定进程等待的方式的。

我们上面演示的就是阻塞式等待,此时第三个参数是0。所谓阻塞等待就是父进程什么也不干,就在等子进程终止,终止以后父进程继续执行,来回收子进程资源并且获取它的退出信息。

非阻塞等待是和阻塞等待相反的,在等待子进程终止期间,父进程还可以干它自己的事情,此时第三个参数是WNOHANG(这个宏定义就直接定义为了1,Wait NO HANG夯住了(停了))。

将等待方式设定为非阻塞等待:

waitpid返回值:

如果 pid_t > 0:等待子进程成功,返回值就是子进程的 pid;
如果 pid_t < 0:等待失败。

如果 pid_t  = 0:在非阻塞等待中,如果子进程没有终止,那么返回0,如果终止且等待成功,返回子进程的pid值。

编译运行:

这是子进程死循环未退出的,现在改为子进程五秒后退出:

编译运行:

这里有一个问题,是进行了非阻塞等待,但是子进程终止了,父进程也没有进行资源回收和退出信息获取啊,因为并没有打印子进程退出的信息。所以这也就是对子进程只询问了一次,发现子进程没有结束父进程就干自己的事了,之后也没有再询问。这样的逻辑执行一次就被叫做非阻塞等待。

而将这部分代码放在一个while循环中,就会进行多次非阻塞等待,也会对子进程进行多次询问,此时叫做轮询:

(此时父进程处理的事应该是可以处理完的,处理完会再一次询问,等待成功后应该跳出循环)

 编译运行:

此时在子进程执行的过程中,父进程在干自己的事之前都会等待一次子进程,当子进程终止以后,父进程在干完自己手头的事情发现子进程终止了,然后获取到了子进程的退出信息。

非阻塞等待的好处就是不会占用父进程的所有时间,父进程可以在轮询期间干自己的事情。

本篇完。

这篇目录不长,但大多是贴图片都一万多字了,还有关于进程控制的最后一篇知识点就放下一篇了,再下一篇是笔试选择题汇总。

下一篇:零基础Linux_11(进程)进程程序替换+实现简单的shell。

相关文章:

零基础Linux_10(进程)进程终止(main函数的返回值)+进程等待

目录 1. 进程终止 1.1 main函数的返回值 1.2 进程退出码和错误码 1.3 进程终止的常见方法 2. 进程等待 2.1 进程等待的原因 2.2 wait 函数 2.3 waitpid 函数 2.4 int* status参数 2.5 int options非阻塞等待 本篇完。 1. 进程终止 进程终止指的就是程序执行结束了&…...

【已解决】opencv 交叉编译 ffmpeg选项始终为NO

一、opencv 交叉编译没有 ffmpeg &#xff0c;会导致视频打不开 在交叉编译时候&#xff0c;发现在 pc 端能用 opencv 打开的视频&#xff0c;但是在 rv1126 上打不开。在网上查了很久&#xff0c;原因可能是 交叉编译过程 ffmpeg 造成的。之前 ffmpeg 是直接用 apt 安装的&am…...

rust生命期

一、生命期是什么 生命期&#xff0c;又叫生存期&#xff0c;就是变量的有效期。 实例1 {let r;{let x 5;r &x;}println!("r: {}", r); }编译错误&#xff0c;原因是r所引用的值已经被释放。 上图中的绿色范围’a表示r的生命期&#xff0c;蓝色范围’b表示…...

实现将一张图片中的目标图片抠出来

要在python中实现将一张图片中的目标图片裁剪出来&#xff0c;需要用到图像处理及机器学习库&#xff0c;以下是一个常用的基本框架 加载图片并使用OpenCV库将其转换为灰度图像 import cv2img cv2.imread(screenshot.jpg) gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)准备模…...

Rust 使用Cargo

Rust 使用技巧 Rust 使用crates 假设你正在编写一个 Rust 程序&#xff0c;要使用一个名为 rand 的第三方库来生成随机数。首先&#xff0c;你需要在 Cargo.toml 文件中添加以下依赖项&#xff1a; toml [dependencies] rand "0.7.3" 然后运行 cargo build&…...

【k8s】集群搭建篇

文章目录 搭建kubernetes集群kubeadm初始化操作安装软件(master、所有node节点)Kubernetes Master初始化Kubernetes Node加入集群部署 CNI 网络插件测试 kubernetes 集群停止服务并删除原来的配置 二进制搭建(单master集群)初始化操作部署etcd集群安装Docker部署master节点解压…...

10.1select并发服务器以及客户端

服务器&#xff1a; #include<myhead.h>//do-while只是为了不让花括号单独存在&#xff0c;并不循环 #define ERR_MSG(msg) do{\fprintf(stderr,"%d:",__LINE__);\perror(msg);\ }while(0);#define PORT 8888//端口号1024-49151 #define IP "192.168.2.5…...

几个好用的测试HTTP请求的网站

Reqres (https://reqres.in)&#xff1a;Reqres提供了一个模拟的REST API&#xff0c;您可以使用它来测试POST、GET、PUT等HTTP请求&#xff0c;并获得相应的响应结果。 JSONPlaceholder (https://jsonplaceholder.typicode.com)&#xff1a;JSONPlaceholder是一个免费的JSON测…...

kafka简易搭建(windows环境)

1&#xff0c;下载 Apache Kafka 查找 kafka_2.13-3.2.1.tgz 2&#xff0c;java版本需要17以上 3&#xff0c;配置server.properties的log.dirs目录、zookeeper.properties 的dataDir目录 windows反斜杠地址 4&#xff0c;启动 cd D:\app\kafka_2.13-3.2.1 .\bin\window…...

毕业设计选题uniapp+springboot新闻资讯小程序源码 开题 lw 调试

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人七年开发经验&#xff0c;擅长Java、Python、PHP、.NET、微信小程序、爬虫、大数据等&#xff0c;大家有这一块的问题可以一起交流&#xff01; &#x1f495;&…...

Linux系统编程基础:进程控制

文章目录 一.子进程的创建操作系统内核视角下的父子进程存在形式验证子进程对父进程数据的写时拷贝 二.进程等待进程非阻塞等待示例: 三.进程替换内核视角下的进程替换过程:综合利用进程控制系统接口实现简单的shell进程 进程控制主要分为三个方面,分别是:子进程的创建,进程等待…...

选择和操作元素

上一篇文档我们介绍了DOM元素和DOM的获取&#xff1b;其实除了获取DOM&#xff0c;我们也可以去替换DOM元素中的文本 document.querySelector(.message).textContent "&#x1f389;Correct Number"● 除此之外&#xff0c;我们可以设置那个数字部分 document.que…...

消息中间件(二)——kafka

文章目录 Apache Kafka综述什么是消息系统&#xff1f;点对点消息类型发布-订阅消息类型 什么是Kafka?优点关键术语Kafka基本原理用例 Apache Kafka综述 在大数据中&#xff0c;会使用到大量的数据。面对这些海量的数据&#xff0c;我们一是需要做到能够收集这些数据&#xf…...

量化交易全流程(四)

本节目录 数据准备&#xff08;数据源与数据库&#xff09; CTA策略 数据源&#xff1a; 在进行量化分析的时候&#xff0c;最基础的工作是数据准备&#xff0c;即收集数据、清理数据、建立数据库。下面先讨论收集数据的来源&#xff0c;数据来源可分为两大类&#xff1a;免…...

idea 如何在命令行快速打开项目

背景 在命令行中从git仓库检出项目&#xff0c;如何在该命令行下快速用idea 打开当前项目&#xff0c;类似vscode 可以通过在项目根目录下执行 code . 快速打开当前项目。 步骤 以macos 为例 vim /usr/local/bin/idea 输入如下内容 #!/bin/sh open -na "IntelliJ IDE…...

YOLOV8-DET转ONNX和RKNN

目录 1. 前言 2.环境配置 (1) RK3588开发板Python环境 (2) PC转onnx和rknn的环境 3.PT模型转onnx 4. ONNX模型转RKNN 6.测试结果 1. 前言 yolov8就不介绍了&#xff0c;详细的请见YOLOV8详细对比&#xff0c;本文章注重实际的使用&#xff0c;从拿到yolov8的pt检测模型&…...

数量关系 --- 方程

目录 一、代入排除法 例题 练习 二、数字特性 例题 练习 整除特性 例题 倍数特性 普通倍数 因子倍数 比例倍数 例题 练习 三、方程法 例题 练习 四、 不定方程&#xff08;组&#xff09; 例题 练习 一、代入排除法 例题 素数&#xff1a…...

【C语言 模拟实现strlen函数的三种方法】

C语言程序设计笔记---022 C语言之模拟实现strlen函数1、介绍strlen函数2、模拟strlen函数的三种方法2.1、计数器法模拟实现strlen函数2.2、递归法模拟实现strlen函数2.3、指针减指针法模拟实现strlen函数 3、结语 C语言之模拟实现strlen函数 前言&#xff1a; 通过C语言字符串…...

MySQL数据库与表管理《三国志》为例

在数据库管理中,一个典型的应用场景是游戏数据的存储和管理。以经典游戏《三国志》为例,该游戏具有多个角色、任务、装备等元素,如何有效地存储和管理这些数据就成为了一个问题。 本文将通过《三国志》的实例,详细解释如何在MySQL中进行数据库和表的管理。 文章目录 《三国…...

D. Jellyfish and Mex - DP

题面 分析&#xff1a; 题目最终需要达到MEX位0&#xff0c;也就是从最开始的MEX变成0后m的最小值&#xff0c;可以设 d p i dp_i dpi​表示当前MEX为 i i i时&#xff0c;m的最小值&#xff0c;那么就可以根据前一个状态推出后一个状态&#xff0c;也就是假如当前MEX是 i i …...

奥斯卡·王尔德

奥斯卡王尔德 奥斯卡王尔德&#xff08;Oscar Wilde&#xff0c;1854年10月16日—1900年11月30日&#xff09;&#xff0c;出生于爱尔兰都柏林&#xff0c;19世纪英国&#xff08;准确来讲是爱尔兰&#xff0c;但是当时由英国统治&#xff09;最伟大的作家与艺术家之一&#xf…...

IDEA常用快捷键大全

整理了一些IDEA开发常用的快捷键&#xff1a; 快捷键组合实现效果psvm Tab键 / main Tab键public static void main(String[] args)sout Tab键System.out.println()Ctrl X删除当前行Ctrl D复制当前行AltInsert(或右键Generate)生成代码(如get,set方法,构造函数等)CtrlAltT…...

Java之多线程的综合练习二

练习六&#xff1a;多线程统计并求最大值 需求&#xff1a; 在上一题基础上继续完成如下需求&#xff1a; 每次抽的过程中&#xff0c;不打印&#xff0c;抽完时一次性打印(随机) 在此次抽奖过程中&#xff0c;抽奖箱1总共产生了6个奖项。 分别为&#xff1a;10,20,100,50…...

selenium下载安装 -- 使用谷歌驱动碰到的问题

安装教程参考: http://c.biancheng.net/python_spider/selenium.html 1. 谷歌浏览器和谷歌驱动版本要对应(但是最新版本谷歌对应的驱动是没有的,因此要下载谷歌历史其他版本): 谷歌浏览器历史版本下载: https://www.chromedownloads.net/chrome64win/谷歌浏览器驱动下载: http:…...

开放式耳机怎么选择、300之内最好的耳机推荐

开放式耳机凭借不入耳、不伤耳、安全更舒适的佩戴体验&#xff0c;得到了越来越多音乐爱好者和专业人士的青睐。开放式耳机不需要插入耳道&#xff0c;在佩戴时可以更加自然和轻松&#xff0c;减少了长时间佩戴引起的不适感&#xff0c;而且不会完全隔绝外界声音&#xff0c;用…...

git密码提交切换SSH提交

git保存密码 每次登录都要输入密码是显示繁琐&#xff0c;好在git提供了保存密码的功能。 在本地工程文件夹下&#xff0c;.git目录&#xff0c;保存以下配置。 [credential] helper store或者 在git bash命令行&#xff0c;执行命令 git config credential.helper store如…...

数字乡村包括哪些方面?数字乡村应用介绍

数字乡村是指利用物联网、数字化和智能化技术&#xff0c;借助现代数字智能产品、高效信息服务和物联网基础设施&#xff0c;以提高农村居民生活质量&#xff0c;助力拓展经济发展前景。 创建数字村庄有助于缩小城乡社区之间的差距&#xff0c;保障每个人都能平等地享受科技发展…...

弹性资源组件elastic-resource设计(一)-架构

简介 弹性资源组件提供动态资源能力,是分布式系统关键基础设施,分布式datax,分布式索引,事件引擎都需要集群和资源的弹性资源能力,提高伸缩性和作业处理能力。 本文介绍弹性资源组件的设计,包括架构设计和详细设计,指导开发人员代码开发 关键词 作业管理器/资源管理器/…...

C/C++笔试面试真题

C/C++笔试面试真题 1、堆和栈的区别 1、栈由系统自动分配,而堆是人为申请开辟; 2、栈获得的空间较小,而堆获得的空间较大; 3、栈由系统自动分配,速度较快,而堆一般速度比较慢; 4、栈是连续的空间,而堆是不连续的空间。 2、什么是野指针?产生的的原因? 野指针的指向的…...

【Vue3】兄弟组件传参

1. 借助父组件传参 A 组件派发一个事件&#xff0c;修改 flag 的值&#xff0c;先传递给父组件&#xff0c;然后由父组件传递给 B 组件。 缺点&#xff1a;必须由 App.vue 处理中间逻辑。 A.vue <template><div class"A"><h1>A组件</h1>…...

提交网站/近期热点新闻事件

利用java打开一张图片&#xff0c;并提取其边缘。功能有打开文件&#xff0c;以及提取边缘。算法原理由于边缘提取的算法有很多种&#xff0c;而提取的精度在相同阈值的情况下也会有不同的结果。这次我的边缘提取使用索贝尔算子(Sobel operator)。该算子会把图像每一点的灰度矢…...

做企业网站的缺点/厦门百度关键词推广

System类&#xff0c;Date类1.System.currentTimeMillis():返回1970年1月1日0时0分0秒到现在的时间戳的差值2.Date类(java.util.Date)public class StringTest01 {public static void main(String[] args) {Date date1 new Date();//创建一个当前时间的Date对象Date date2 ne…...

武汉专业网站排名推广/影视后期哪个培训靠谱

考试路线 1 【2】 3 转载于:https://www.cnblogs.com/rhxuza1993/p/9485975.html...

国内包装设计网站/百度浏览器打开

第一次, 写点啥呢? 分享一下订阅的资源吧! 1 <?xml version"1.0" encoding"UTF-8"?>2 3 <opml version"1.0">4 <head>5 <title>建勇 subscriptions in feedly Cloud</title>6 </head>7…...

关于工装设计的网站/公司怎么建立自己的网站

今天又搞了下jsp servlet 的代码样例&#xff0c;感觉虽然搭了好多次&#xff0c;可是每次还是不记得那些参数&#xff0c;都要去网上搜索&#xff0c;索性自己把这次的简单demo给记录下来&#xff0c;供下次使用的时候直接复制吧。这个web逻辑 input.jsp ---->ReportServle…...

用文字写美食个人网站设计作品/网站做seo教程

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2022年低压电工理论题库是低压电工全部考试题库全真模拟题&#xff01;2022年低压电工考试题模拟考试题库模拟考试平台操作根据低压电工考试大纲。低压电工考试资料通过安全生产模拟考试一点通上提前检验学习成果。 1…...