5守护进程与线程
进程组
多个进程的集合,第一个进程就是组长,组长进程的PID等于进程组ID。
进程组生存期:进程组创建到最后一个进程离开(终止或转移到另一个进程组)。与组长进程是否终止无关。
一个进程可以为自己或子进程设置进程组 ID
相关函数
pid_t getpgrp(void);
得到当前进程所在的进程组的组 IDpid_t getpgid(pid_t pid);
获取指定的进程所在的进程组的组 ID,参数 pid 就是指定的进程,0当前进程int setpgid(pid_t pid, pid_t pgid);
将某个进程移动到其他进程组中或者创建新的进程组参数:pid: 某个进程的进程 IDpgid: 某个进程组的组 ID如果 pgid 对应的进程组存在,pid 对应的进程会移动到这个组中,pid != pgid如果 pgid 对应的进程组不存在,会创建一个新的进程组,因此要求 pid == pgid, 当前进程就是组长了返回值:函数调用成功返回 0,失败返回 - 1
setpgid设置子进程组id
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>int main(int argc, char *argv[])
{pid_t pid;pid = fork();if(pid == 0 ){printf("我是子进程:%d,我的进程组id是:%d\n",getpid(),getpgrp());setpgid(pid,pid); //设置子进程的组id为自己的pid,默认是父进程的pidprintf("我是子进程:%d,我的进程组id是:%d\n",getpid(),getpgrp());}else if(pid > 0){sleep(1);printf("我是父进程:%d,我的进程组id是:%d\n",getpid(),getpgrp());wait(NULL);}return 0;
}
会话
多个进程组的集合
获取进程所属的会话 ID
pid_t getsid(pid_t pid);
成功:返回调用进程的会话 ID;失败:-1,设置 errno
pid 为 0 表示察看当前进程 session ID创建一个会话,并以自己的 ID 设置进程组 ID,同时也是新会话的 ID。
pid_t setsid(void);
成功:返回调用进程的会话 ID;失败:-1,设置 errno
调用了 setsid 函数的进程,既是新的会长,也是新的组长。
注意事项:
调用进程不能是进程组组长,该进程变成新会话首进程(session header),建立新会话时,先调用 fork, 父进程终止,子进程调用 setsid(),
#include <stdio.h>
#include <unistd.h>int main(int argc, char *argv[])
{pid_t pid;pid = fork();if(pid == 0){printf("我是子进程id:%d,进程组id:%d,会话id:%d\n",getpid(),getpgid(0),getsid(0));printf("change--------------\n");sleep(2);setsid();printf("我是子进程id:%d,进程组id:%d,会话id:%d\n",getpid(),getpgid(0),getsid(0));}else{sleep(3);printf("我是父进程id:%d,进程组id:%d,会话id:%d\n",getpid(),getpgid(0),getsid(0));}return 0;
}
编译执行结果
我是子进程id:44801,进程组id:44800,会话id:39560 #默认子进程的进程组id是父进程的pid,会话id是当前bash的pid
change--------------
我是子进程id:44801,进程组id:44801,会话id:44801 #setsid后,进程组id,会话id都变成子进程的pid
我是父进程id:44800,进程组id:44800,会话id:39560
守护进程
daemon进程。通常运行与操作系统后台,脱离控制终端。一般不与用户直接交互。周期性的等待某个事件发生或周期性执行某一动作。
不受用户登录注销影响。通常采用以d结尾的命名方式。
Linux 后台的一些系统服务进程,没有控制终端,不能直接和用户交互。不受用户登录、注销的影响,一直在运行着,他们都是守护进程。
创建守护进程
创建守护进程,最关键的一步是调用 setsid 函数创建一个新的 Session,并成为 Session Leader。
1. fork子进程,让父进程终止。2. 子进程调用 setsid() 创建新会话3. 通常根据需要,改变工作目录位置 chdir(), 防止目录被卸载。4. 通常根据需要,重设umask文件权限掩码,影响新文件的创建权限。 022 -- 755 0345 --- 432 r---wx-w- 4225. 通常根据需要,关闭/重定向 文件描述符6. 守护进程 业务逻辑。while()
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
#include <string.h>void func(int signo)
{int fd1;fd1 = open("./lc.txt",O_RDWR|O_CREAT|O_APPEND,0664); //fd1 = 3 符合默认的习惯if(fd1 == -1 ){perror("open lc.txt error");exit(1);}char *str="heppy new year\n";write(fd1,str,strlen(str));close(fd1);
}int main(int argc, char *argv[])
{pid_t pid;int fd,fd1;pid = fork();if(pid > 0){exit(1);}pid_t pid1 = setsid();if(pid1 == -1 ){perror("open lc.txt error");exit(1);}chdir("/home/lc"); //切换到一个不可能被删除卸载的目录umask(0022); //默认umask是0002,默认创建普通文件默认属性是664close(STDIN_FILENO); //close 0fd = open("/dev/null",O_RDWR); //fd = 0if(fd == -1 ){perror("open /dev/null error");exit(1);}dup2(fd, STDOUT_FILENO); // 重定向 stdout和stderr 1 -->0dup2(fd, STDERR_FILENO); // 2--> 0,//捕捉信号struct sigaction act;act.sa_handler = func;act.sa_flags = 0;sigemptyset(&act.sa_mask);sigaction(SIGALRM,&act,NULL);
// signal(SIGALRM,func);//设置定时器struct itimerval it;it.it_interval.tv_sec = 10;it.it_interval.tv_usec = 0;it.it_value.tv_sec = 10;it.it_value.tv_usec = 0;setitimer(ITIMER_REAL,&it,NULL);while (1); // 模拟 守护进程业务.return 0;
}
线程
LWP,(light weight process)轻量级的进程,在linux环境下线程的本质仍然是进程,
进程:有独立的 进程地址空间。有独立的pcb。 分配资源的最小单位。可看成是只有一个线程的进程线程:有独立的pcb。没有独立的进程地址空间。 最小单位的执行。
[root@lc133 ~]# ps -aux | grep mysql | grep -v grep
mysql 1620 0.4 20.2 1793004 405880 ? Ssl 08:20 1:36 /usr/sbin/mysqld
Ssl:休眠,拥有子进程,多线程
[root@lc133 ~]# ps -Lf 1620
UID PID PPID LWP C NLWP STIME TTY STAT TIME CMD
mysql 1620 1 1620 0 38 08:20 ? Ssl 0:01 /usr/sbin/mysqld
mysql 1620 1 1669 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1670 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1671 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1672 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1674 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1675 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1676 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1677 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1678 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1679 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1680 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1724 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1725 0 38 08:20 ? Ssl 0:04 /usr/sbin/mysqld
mysql 1620 1 1726 0 38 08:20 ? Ssl 0:04 /usr/sbin/mysqld
mysql 1620 1 1727 0 38 08:20 ? Ssl 0:04 /usr/sbin/mysqld
mysql 1620 1 1728 0 38 08:20 ? Ssl 0:04 /usr/sbin/mysqld
mysql 1620 1 1729 0 38 08:20 ? Ssl 0:55 /usr/sbin/mysqld
mysql 1620 1 1786 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1787 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1788 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1793 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1794 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1797 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1799 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1802 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1803 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1804 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1811 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1812 0 38 08:20 ? Ssl 0:05 /usr/sbin/mysqld
mysql 1620 1 1814 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1815 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1816 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1817 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1830 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1831 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1832 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqld
mysql 1620 1 1836 0 38 08:20 ? Ssl 0:00 /usr/sbin/mysqldlwp:线程号
系统会给mysql进程1620分配进程地址空间,内核空间拥有pid1620的pcb。
pid1620进程创建线程时,本身也成了主线程。创建的线程分别拥有自己独立的pcb,处在同一内核空间中。
线程更加节省系统资源,效率不仅可以保持的,而且能够更高在一个地址空间中多个线程独享:每个线程都有属于自己的栈区,寄存器 (内核中管理的)1.线程 id2.处理器现场和栈指针(内核栈)3.独立的栈空间(用户空间栈)4.errno 变量5.信号屏蔽字6.调度优先级在一个地址空间中多个线程共享:代码段,堆区,全局数据区,打开的文件 (文件描述符表) 都是线程共享的1.文件描述符表2.每种信号的处理方式3.当前工作目录4.用户 ID 和组 ID5.内存地址空间 (.text/.data/.bss/heap/共享库)每个进程对应一个虚拟地址空间,一个进程只能抢一个 CPU 时间片一个地址空间中可以划分出多个线程,在有效的资源基础上,能够抢更多的 CPU 时间片一个进程创造线程并不是越多越好优点: 1. 提高程序并发性 2. 开销小 3. 数据通信、共享数据方便
缺点: 1. 库函数,不稳定 2. 调试、编写困难、gdb 不支持 3. 对信号支持不好
优点相对突出,缺点均不是硬伤。Linux 下由于实现方法导致进程、线程差别不是很大。
pthread_self获取当前线程id
获取线程 ID。其作用对应进程中 getpid() 函数。pthread_t pthread_self(void);返回值:成功:0; 失败:无!线程 ID:pthread_t 类型,本质:在 Linux 下为%lu无符号整数,其他系统中可能是结构体实现线程 ID 是进程内部,识别标志。(两个进程间,线程 ID 允许相同)注意:在子线程中通过使用pthread_self,获得线程id。
pthread_create创建线程
创建一个新线程。 其作用对应进程中 fork() 函数。int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);返回值:成功:0; 失败:错误号 -----Linux 环境下,所有线程特点,失败均直接返回错误号。参数:pthread_t:当前 Linux 中可理解为:typedef unsigned long int pthread_t;参数 1:传出参数,保存系统为我们分配好的线程 ID参数 2:通常传 NULL,表示使用线程默认属性。若想使用具体属性也可以修改该参数。参数 3:函数指针,指向线程主函数(线程体),该函数运行结束,则线程结束。参数 4:线程主函数执行期间所使用的参数。传参。
pthread_exit退出当前线程
void pthread_exit(void *retval); 退出当前线程。参数:线程退出的时候携带的数据,当前子线程的主线程会得到该数据。如果不需要使用,指定为 NULL几个退出函数:exit(); 退出当前进程。后续代码不会执行return: 返回到调用者那里去。pthread_exit(): 退出当前线程。不影响其他进程
循环创建线程
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>void *func(void *arg)
{int i = (int)arg;printf("我是第%d子线程线程id:%lu,主线程是:%d\n",i+1,pthread_self(),getpid());//return NULL;if(i==4){while(1);}pthread_exit(NULL);
}int main(int argc, char *argv[])
{pthread_t tid;int i;for(i = 0; i < 5; i++){int ret = pthread_create(&tid,NULL,func,(void*)i);if(ret != 0){perror("pthread_create error");exit(1);}}//sleep(1);printf("我是主线程线程id:%lu,主线程是:%d\n",pthread_self(),getpid());//while(1);//return 0;pthread_exit(NULL);
}
主线程 pthread_exit(NULL);只退出当先线程,不会对其他线程造成影响。
[lc@lc133 pthread]$ gcc pthread.c -lpthread
pthread.c: 在函数‘func’中:
pthread.c:8:10: 警告:将一个指针转换为大小不同的整数 [-Wpointer-to-int-cast]int i = (int)arg;^
pthread.c: 在函数‘main’中:
pthread.c:23:43: 警告:将一个整数转换为大小不同的指针 [-Wint-to-pointer-cast]int ret = pthread_create(&tid,NULL,func,(void*)i);^
[lc@lc133 pthread]$ ./a.out
我是主线程线程id:140307387344704,主线程是:25356
我是第3子线程线程id:140307362223872,主线程是:25356
我是第2子线程线程id:140307370616576,主线程是:25356
我是第1子线程线程id:140307379009280,主线程是:25356
我是第4子线程线程id:140307353831168,主线程是:25356
我是第5子线程线程id:140307345438464,主线程是:25356
[root@lc133 ~]# ps -aux | grep a.out #使用pthread_exit主线程已退出,子线程还在,使用return函数,主线程退出,子进程也会退出
lc 25356 100 0.0 0 0 pts/1 Zl+ 14:51 0:58 [a.out] <defunct>
root 25373 0.0 0.1 112840 2512 pts/0 S+ 14:52 0:00 grep --color=auto a.out
pthread_join阻塞 回收线程
int pthread_join(pthread_t thread, void **retval); 阻塞 回收线程。thread: 待回收的线程idretval:传出参数。 回收的那个线程的退出值。线程异常借助,值为 -1。返回值:成功:0失败:errno
pthread_exit可以传出指针,数值,要注意数据格式的强转。
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>struct student
{int age;char name[256];
};void *func(void *arg)
{printf("child thread,process id is %d,thread id is %lu\n",getpid(),pthread_self());struct student *luci;luci = malloc(sizeof(struct student));memset(luci,0,sizeof(luci));luci->age = 17;strcpy(luci->name,"luci");pthread_exit((void *)luci);
}int main(int argc, char *argv)
{printf("main thread,process id is %d,thread id is %lu\n",getpid(),pthread_self());pthread_t tid;int ret = pthread_create(&tid,NULL,func,NULL);if(ret != 0){perror("pthread_creade error");exit(1);}struct student *retval;//pthread_join 传出参数retval是void**类型的ret = pthread_join(tid,(void **)&retval);if(ret != 0){perror("pthread_jion error");exit(1);}printf("child thread exit.\n");printf("age = %d ,name = %s \n",retval->age,retval->name);return 0;
}
#include <stdio.h>
#include <pthread.h>void *func(void *arg)
{printf("child pthread id : %lu\n",pthread_self());pthread_exit((void*)66);
}int main(){pthread_t tid;int *retval;pthread_create(&tid,NULL,func,NULL);pthread_join(tid,(void**)&retval) ;printf("main pthread receive : %d\n",(void *)retval);pthread_exit(NULL);
}
pthread_detach 设置线程分离
int pthread_detach(pthread_t thread); 设置线程分离thread: 待分离的线程id返回值:成功:0失败:errno
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>void *func(void *arg)
{int i;for( i = 0;i < 5; i++){sleep(1);printf("i = %d \n",i);}pthread_exit(NULL);}
int main()
{pthread_t tid;int ret;ret = pthread_create(&tid,NULL,func,NULL);if(ret != 0){fprintf(stderr,"pthread_create error:%d",strerror(ret));exit(1);}pthread_detach(tid);ret = pthread_join(tid,NULL);//线程分离后主线程就不能回收了,报错:无效的参数if(ret != 0){fprintf(stderr,"pthread_join error:%s",strerror(ret));exit(1);}pthread_exit(NULL);return 0;
}
pthread_cancel杀死一个线程
int pthread_cancel(pthread_t thread); 杀死一个线程。 需要到达取消点(保存点)thread: 待杀死的线程id返回值:成功:0失败:errno在线程 A 中调用线程取消函数 pthread_cancel,指定杀死线程 B,这时候线程 B 是死不了的,只有在线程 B 中进程进行一次系统调用(从用户区切换到内核区),这个节点会被pthread_cancel杀死,否则线程 B 可以一直运行。与信号不同,进程会优先处理信号。如果,子线程没有到达取消点, 那么 pthread_cancel 无效。我们可以在程序中,手动添加一个取消点。使用 pthread_testcancel();成功被 pthread_cancel() 杀死的线程,返回 -1.使用pthead_join 回收。
pthread_equal判断线程id是否相同
int pthread_equal(pthread_t t1, pthread_t t2);参数:t1 和 t2 是要比较的线程的线程 ID返回值:如果两个线程 ID 相等返回非 0 值,如果不相等返回 0
与进程函数相比
线程控制原语 进程控制原语pthread_create() fork();pthread_self() getpid();pthread_exit() exit(); / return pthread_join() wait()/waitpid()pthread_cancel() kill()pthread_detach()
创建线程时设置线程分离属性
pthread_create函数中参数 pthread_attr_t 是一个结构体
typedef struct
{int detachstate; // 线程的分离状态int schedpolicy; // 线程调度策略structsched_param schedparam; // 线程的调度参数int inheritsched; // 线程的继承性int scope; // 线程的作用域size_t guardsize; // 线程栈末尾的警戒缓冲区大小int stackaddr_set; // 线程的栈设置void* stackaddr; // 线程栈的位置size_t stacksize; // 线程栈的大小
} pthread_attr_t;
步骤:pthread_attr_t attr 创建一个线程属性结构体变量pthread_attr_init(&attr); 初始化线程属性,成功:0;失败:错误号pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);设置线程属性为 分离态//detachstate: PTHREAD_CREATE_DETACHED(分离线程)// PTHREAD _CREATE_JOINABLE(非分离线程)//获取程属性,分离 or 非分离//int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate); //参数: attr:已初始化的线程属性pthread_create(&tid, &attr, tfn, NULL); 借助修改后的 设置线程属性 创建为分离态的新线程pthread_attr_destroy(&attr); 销毁线程属性,成功:0;失败:错误号
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>void *func(void *arg)
{printf("hello wrold.\n");pthread_exit(NULL);
}int main()
{pthread_attr_t attr;pthread_attr_init(&attr);pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);int val;pthread_attr_getdetachstate(&attr,&val);printf("属性:%d\n",val);pthread_t tid;pthread_create(&tid,&attr,func,NULL);pthread_attr_destroy(&attr);sleep(1);int ret = pthread_join(tid,NULL);if(ret != 0){fprintf(stderr,"pthread_join error : %s\n",strerror(ret));exit(1);}pthread_exit(NULL);return 0;
}
[lc@lc pthread]$ ./a.out
属性:1
hello wrold.
pthread_join error : Invalid argument
//pthread_join报错成功分离
注意事项
1. 主线程退出其他线程不退出,主线程应调用 pthread_exit
2. 避免僵尸线程
pthread_join
pthread_detach
pthread_create 指定分离属性
被 join 线程可能在 join 函数返回前就释放完自己的所有内存资源,所以不应当返回被回收线程栈中的值;
3. malloc 和 mmap 申请的内存可以被其他线程释放
4. 应避免在多线程模型中调用 fork 除非,马上 exec,子进程中只有调用 fork 的线程存在,其他线程在子进程
中均 pthread_exit
5. 信号的复杂语义很难和多线程共存,应避免在多线程引入信号机制
相关文章:
5守护进程与线程
进程组 多个进程的集合,第一个进程就是组长,组长进程的PID等于进程组ID。 进程组生存期:进程组创建到最后一个进程离开(终止或转移到另一个进程组)。与组长进程是否终止无关。 一个进程可以为自己或子进程设置进程组 ID 相关函数 pid_t …...

EZ-Cube简易款下载器烧写使用方法
一、硬件连接 跟目标芯片接4根线 VCC、GND、TOOL、REST 四根线,如果板子芯片自己外接电源的,VCC 线可以不接。 二、 安装烧写软件和驱动 烧写软件:https://download.csdn.net/download/Stark_/87444744?spm1001.2014.3001.5503 驱动程序&a…...

sql server安装并SSMS连接
博主简介:原互联网大厂tencent员工,网安巨头Venustech员工,阿里云开发社区专家博主,微信公众号java基础笔记优质创作者,csdn优质创作博主,创业者,知识共享者,欢迎关注,点赞ÿ…...

Python_pytorch (二)
python_pytorch 小土堆pytotch学习视频链接 from的是一个个的包(package) import 的是一个个的py文件(file.py) 所使用的一般是文件中的类(.class) 第一步实例化所使用的类,然后调用类中的方法(def) Torchvision 数据集 数据集使用(CI…...

java手机短信验证,并存入redis中,验证码时效5分钟
目录 1、注册发送短信账号一个账号 2、打开虚拟机,将redis服务端打开 3、创建springboot工程,导入相关依赖 4、写yml配置 5、创建controller层,并创建controller类 6、创建service层,并创建service类 7、创建工具类&#x…...

kubectl命令控制远程k8s集群(Windows系统、Ubuntu系统、Centos系统)
文章目录1. 本地是linux2. 本地是Windows1. 本地是linux 安装kubectl命令 法一:从master的/usr/bin目录下拷贝kubectl文件到本机/usr/bin目录下法二:GitHub下载kubectl文件 在家目录下创建.kube目录config文件 法一:将master上对应用户的~/.…...

【求解器-COPT】COPT的版本更新中,老版本不能覆盖的问题
【求解器-COPT】COPT的版本更新中,老版本不能覆盖的问题方法1方法2如果license还是找不到作者:刘兴禄 参考网址: COPT的下载和配置步骤如下: 教程 | Windows系统下如何安装COPT求解器并配置许可文件: https://zhuan…...

Vue3.0文档整理:一、简介
1.1:什么是vue? Vue是一款用于构建用户界面的javascript框架;它基于标准HTML、CSS和Javascript构建,并提供了一套声明式、组件化的编程模型,帮助你高效的开发用户界面。 1.2:MVVM工作原理 MVVM指的是model、view和vie…...

vue2 diff算法及虚拟DOM
概括:diff算法,虚拟DOM中采用的算法,把树形结构按照层级分解,只比较同级元素,不同层级的节点只有创建和删除操作。 一、虚拟DOM (1) 什么是虚拟DOM? 虚拟 DOM (Virtual DOM,简称 VDOM) 是一种…...

Ray和极客们的创新之作,2月18日来发现
所在论坛:数据库技术创新&云原生论坛分享时段:2.18 10:30-11:00分享主题:云原生数据库PieCloudDB :Unbreakable安全特性剖析分享嘉宾:王淏舟,拓数派资深研发工程师 由中国开源软件推进联盟PostgreSQL分…...
Dubbo 源码分析 – 集群容错之 Router
1. 简介 上一篇文章分析了集群容错的第一部分 – 服务目录 Directory。服务目录在刷新 Invoker 列表的过程中,会通过 Router 进行服务路由。上一篇文章关于服务路由相关逻辑没有细致分析,一笔带过了,本篇文章将对此进行详细的分析。首先&…...

行人检测(人体检测)3:Android实现人体检测(含源码,可实时人体检测)
行人检测(人体检测)3:Android实现人体检测(含源码,可实时人体检测) 目录 行人检测(人体检测)3:Android实现人体检测(含源码,可实时人体检测) 1. 前言 2. 人体检测数据集说明 3. 基于YOLOv5的人体检测模型训练 4.人体检测模型…...

【图像分类】基于PyTorch搭建LSTM实现MNIST手写数字体识别(单向LSTM,附完整代码和数据集)
写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 提起LSTM大家第一反应是在NLP的数据集上比较常见,不过在图片分类中,它同样也可以使用。我们以比较熟悉的 mnist…...

Kotlin 1.8.0 现已发布,有那些新特性?
文章目录**如何安装 Kotlin 1.8.0****如果您遇到任何问题****更多文章和视频**结语Kotlin 1.8.0 版本现已发布,以下是其部分最大亮点: JVM 的新实验性功能:递归复制或删除目录内容提升了 kotlin-reflect 性能新的-Xdebug编译器选项ÿ…...

likeshop单商户SaaS商城系统—无限多开,搭建多个商城
likeshop单商户SaaS商城系统:适用于多开(SaaS)、B2C、单商户、自营商城场景,完美契合私域流量变现闭环交易使用,系统拥有丰富的营销玩法,强大的分销能力,支持DIY多模板,前后端分离。…...

Bean(Spring)的执行流程和生命周期
Bean(Spring)的执行流程具体的流程就和我们创建Spring基本相似。启动 Spring 容器 -> 实例化 Bean(分配内存空间,从无到有) -> Bean 注册到 Spring 中(存操作) -> 将 Bean 装配到需要的…...

工作记录------PostMan自测文件导入、导出功能
工作记录------PostMan自测文件导入、导出功能 测试文件导出 背景:写了一个文件下载功能,是数据写到excel中,下载,使用PostMan点击send后,返回报文是乱码。 解决办法: 点击send下面的 send and Downlo…...

上海亚商投顾:沪指震荡上行 大消费板块全线走强
上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。市场情绪三大指数今日震荡反弹,沪指全天低开高走,深成指、创业板指均涨超1%。工程机械板块集体大涨&a…...
linux中的图形化UDP调试工具
sokit freeware version: 1.3.1 (GPLv3) website: https://github.com/sinpolib/sokit/ 这是一个TCP / UDP数据包收发和传输工具 linux汉化 默认是英文版本的,如果想使用中文,把软件目录下的sokit.lan_rename重命令为sokit.lan再次打开软件就发现已经…...

前端react面试题指南
概述下 React 中的事件处理逻辑 抹平浏览器差异,实现更好的跨平台。避免垃圾回收,React 引入事件池,在事件池中获取或释放事件对象,避免频繁地去创建和销毁。方便事件统一管理和事务机制。 为了解决跨浏览器兼容性问题࿰…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...