linux进程全解

目录 一、程序的开始和结束二、进程环境三、进程的正式引入四、fork创建子进程五、父子进程对文件的操作六、进程的诞生和消亡七、父进程wait回收子进程八、waitpid介绍九、exec族函数及实战十、进程状态和system函数十一、进程关系十二、守护进程的引入十三、编写简单守护进程十四、使用syslog来记录调试信息十五、让程序不能被多次运行十六、linux的进程间通信概述十七、linux的IPC机制1-管道十八、SystemV IPC介绍 一、程序的开始和结束 1、main函数由谁调用 (1)编译链接时的引导代码。 操作系统下的应用程序其实在main执行前也需要先执行一段引导代码才能去执行main(如同ARM开发板裸机程序开始用汇编代码构建C语言运行的环境),我们写应用程序时不用考虑引导代码的问题,编译链接时(准确说是链接时)由链接器将编译器中事先准备好的引导代码给链接进去和我们的应用程序一起构成最终的可执行程序。 (2)运行时的加载器。 加载器是操作系统中的程序,当我们去执行一个程序时(譬如./a.out,譬如代码中用exec族函数来运行)加载器负责将这个程序加载到内存中去执行这个程序。 (3)程序在编译链接时用链接器,运行时用加载器,这两个东西对程序运行原理非常重要。 (4)argc和argv的传参如何实现 argc是int类型,表示运行程序的时候给main函数传递了几个参数; argv是一个字符串数组,这个数组用来存储多个字符串,每个字符串就是我们给main函数传的一个参数。 argv[0]就是我们给main函数的第一个参数,argv[1]就是传给main的第二个参数是编译链接的引导代码给main函数传参的。 int main(int argc, char* argv) { return 0; } 2、程序如何结束 https://www.cnblogs.com/mickole/p/3186606.html (1)正常终止:return、exit、_exit/_Exit (2)非正常终止:自己或他人发信号终止进程 3、atexit注册进程终止处理函数 atexit() 函数:注册终止函数 即main执行结束后调用的函数。它的原型是一个返回值为空,参数为返回值为空的函数指针 #include<stdlib.h> void atexit(void (*func)(void)) (1)atexit(),注册的终止处理函数最后执行。即使该语句在程序的开头。 (2)atexit注册多个进程终止处理函数,先注册的后执行(先进后出,和栈一样) (2)return、exit和_exit的区别:return和exit效果一样,都是会执行进程终止处理函数,但是用_exit终止进程时并不执行atexit注册的进程终止处理函数。 _exit 函数的作用是:直接使进程停止运行,清除其使用的内存空间,并清除其在内核的各种数据结构; exit 函数则在这些基础上做了一些小动作,在执行退出之前还加了若干道工序。exit() 函数与 _exit() 函数的最大区别在于:exit()函数在调用exit系统调用前,要检查文件的打开情况,把文件缓冲区中的内容写回文件。“清理I/O缓冲”。另外注意_exit是一个系统调用,exit是一个c库函数。 回调函数:回调函数就是一个被作为参数传递的函数。在C语言中,回调函数只能使用函数指针实现。当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。 #include <stdio.h> #include <stdlib.h> #include <unistd.h> void func1(void); void func2(void); void func1(void) { printf("The first to register:I will go.\n"); } void func2(void) { printf("

Vue项目使用多个服务器地址的请求方法

由于后端进行多模块开发,会用到不同的服务器,前端开发时就会被要求请求多个服务器地址,应对这种情况,分以下几种解决方案: 1.如果项目开发初期,应用多个服务器地址且每个地址都应用十分频繁,建议重新封装request。 2.果项目已经开发很久了,且上线过版本,此时建议封装request2.js文件,虽然笨,但胜在有效,因为贸然更改前人配置好的文件,报错了你可能找不到关键。 3.如果只是少量应用其他服务器地址,可以用axios请求,不用封装的request,但缺点就是上线前记得改线上地址。也可以单独写一个baseAPI引用过去,这样就不用一个一个得改了。 前两种有时间补上,先放个第三种懒人写法 注意:带上token // 直接用axios请求 export function find(Id) { return axios.get(`http://XXX.XXX.com/api/XXX/XXX/XXX/${Id}`,{headers:{'Authorization' : getToken()}}) } // 再加一个baseapi export function find(Id) { return axios.get(`${baseApi1}/api/XXX/XXX/XXX/${Id}`,{headers:{'Authorization' : getToken()}}) }

vuex中的...mapState与...mapMutations的使用以及mapGetters存在的意义

1、mapState、mapGetters在何处使用?区别是什么 ? 无论是state或者getters中的数据,在页面中使用时都是注入到当前的计算属性中。一般是挂在computed里面的,因为如果挂在data上面,只会赋值一次,不会跟着vuex里面的数据变化而同步变化,当然也可以通过watch $store去解决。 mapState、mapGetters都是在computed中直接使用的,那mapGetters还有存在的必要吗? 后者存在的意义是对 state 的计算属性,本质是对 state 中的数据进行一些计算,比例如数据的修饰之类的,这其实是一个代码解耦的过程。如果有做某些数据的格式化处理使用到getter的话,如果只是简单的取数据,赋值,则仅仅是state和mutation足以。但是并不能说 mapGetters 没有存在的意义,只是你把 state 中的数据在 mutation 阶段就处理掉完了(计算),所以就用不到 getters 做计算,只需要直接访问 state。 2、在页面中通过$store来使用vuex中的数据 ①挂在计算属性中,用this.$store.state或this.$store.getters取值 computed: { hasBg(){ return this.$store.state.hasBg } } ②在data中使用,结合watch使得vuex与页面数据同步(不推荐) data() { return { userName:this.$store.state.userName }; }, watch : { '$store.state.userName' : { handler(newVal,oldVal) { this.userName = newVal } } } 3、使用...mapState与...mapMutation ...mapState与...mapMutation就是第一种方法的简便写法 import { mapState } form 'vuex' ..... computed: { //数组的写法:相对于age(){ruturn this.$store.state.age} ps:用引号包着 ...mapState(['age','name','sex']) //对象的写法:若需要重命名则采用对象形式 ...mapState({nianling:'age',xingming:'name',xingbie:'sex'}) ...mapMutation的使用与...mapState相同,只是放在methods中。借助mapMutations生成对应的方法,方法中会调用commit去联系mutations

vue配置项---watch的使用

watch有四种常用用法 情况一:基础监听,比如监听data中定义的某个数据。 data() { return { msg: "hello", }; }, watch: { msg(newmsg, oldmsg) { console.log(newmsg); }, }, 直接写一个监听处理函数,默认参数第一个是新值,第二个是旧值。每次监听到msg变化都会执行这个函数。 情况二:使用handle方法immediate与deep属性。 data() { return { msg: { name: "liu", age: "18", }, }; }, watch: { msg: { handler(newmsg, oldmsg) { console.log(newmsg); }, immediate: true, deep: true, }, } 一般情况下,在数据第一次绑定时不会执行监听函数,只有当值变化时才会执行监听函数。此时将immediate设置为true可以实现首次监听。 当监听对象的改变时普通的watch方法无法监听对象内部属性的变化,需要设置deep属性,开启深度监听deep为true时则改对象中的所有属性都会被监听,对象中每个属性改变都会执行handler函数。如果只想监听对象中某个属性的变化可以用如下写法...(情况三) 情况三:只监听对象中的某个属性 data() { return { msg: { name: "liu", age: "18", }, }; }, watch: { "msg.name": { //键路径必须加上引号 handler(newmsg, oldmsg) { console.

数字信号处理笔记01:离散时间信号与系统

一、离散时间序列 1. 序列的表示 离散时间信号也称为离散时间序列 2. 序列的分类 序列长度:有限长序列和无限长序列 序列周期性:周期序列和非周期序列 序列函数值:实数序列和复数序列 能量序列: 功率序列: 3. 常用时间序列 二者关系: 连续的周期信号,其对应的离散时间序列不一定具有周期性 4. 序列的分解 二、离散时间系统 1. 系统的表示 2. 系统的分类 (1)无记忆系统:系统的输出只与当前时刻的输入有关 (2)线性系统:系统的输入与输出满足齐次性和叠加性 (3)时不变系统:系统的特性不随时间而变化 (4)因果系统:当前时刻输出仅取决于当前及以前时刻的输入,而与以后的输入无关 (5)稳定系统:有界输入产生有界输出,则系统稳定 3. LTI系统的卷积和表示 4. LTI系统的性质 (1)交换律 (2)结合律 (3)分配律 (4)LTI因果性判据 (5)LTI系统稳定性判据

7. Python type( )函数——查询数据类型

7. type( )函数——查询数据类型 文章目录 7. type( )函数——查询数据类型1. print( )函数知识回顾2. 什么是type( )函数3. type( )函数的语法4. type( )函数的返回值5. type( )函数示例【示例1】【示例2】【示例3】【示例4】 6. 总结7. 课后练习 1. print( )函数知识回顾 print( )函数:Python中的输出函数,作用是将print( )函数括号里的内容输出到屏幕上。 print( )函数的语法 print( )函数由4部分组成: 1.函数名:print 2.英文小括号:( ) 3.英文引号(有4种使用情形) 4.要输出的内容 2. 什么是type( )函数 type[taɪp]:类型。 type的中文意思是类型。 type( )函数在Python中的作用是查询括号中的内容的数据类型。 print( )函数:输出函数。 type( )函数:查询数据类型函数。 【功能】查询type( )函数括号中的内容的数据类型。 3. type( )函数的语法 type( )函数的语法与print( )函数的语法类似。 type( )函数由3部分组成: 1.函数名:type 2.英文小括号:( ) 3.要查询的内容。(内容是变量或具体的数据内容) 函数括号里的值我们通常称为参数。 【type函数的参数为变量】 【type函数的参数为具体的数据本身】 4. type( )函数的返回值 1.str:表示数据类型为字符串 2.int:表示数据类型为整数 3.float:表示数据类型为浮点数

Stanford CS143 速通PA1教程

今天做完了CS143的PA1,感觉最难的地方在于官方没有具体的文档(edX),然后COOL语言调试比较困难,以下是我对同样打算入坑CS143的同学的一些帮助吧: 速通前的准备 Virtual VM Setup:如果还没有搭好环境的,建议跟着官网的搭一下,我选择的是傻瓜式的搭建方法,就是用官方给的环境,这个最方便,也不容易出问题。PA1.pdf(见我的仓库):没有在edX找到文档,这是我从别人的仓库借鉴过来的,里面详细地说明了要求的。cool-manual.pdf(见我的仓库):同样是补充材料,很有用,在做之前可以先通读下,了解下COOL语言的语法,当然上课讲的几个例子(02-01 ~ 02-03)也需要过一遍。example里面的list.cl:这个很有用,因为它作为链表,利用头插的方式实现,与栈的思想是一致的,改一改就可以做成栈了。 我的体会 以上三个看完(manual可以作为语法的补充,用的时候看),就可以着手写了,当然写得还是比较难受,毕竟是一门新的语言,然后其实最大的坑在于,COOL的调试非常拉跨,所以很多时候你只是模糊地知道在某一行的附近发生了错误,我遇到的一些坑如下: if then else是一个整体,不能没有then,或者else不能在代码段中声明变量 代码实现与资料: 上述资料和我的代码实现,都在这个仓库里面

kali怎么更新

首先打开kali终端 其次输入命令apt-get update然后静等跑命令 跑完命令然后直接apt-get upgrade 第一次更新可能要等上一两小时耐心等就行了 如果出现网络不可达的情况就换个kali源试试

eNSP综合实验2

本次实验主要包含链路聚合、生成树协议、Vlan通信、跨Vlan通信(单臂路由实现)、NAT地址转换和访问控制、静态路由、多自治系统OSPF以及路由引入 、DHCP以及Telnet远程登陆 本实验分成两个模块完成。即内部网络和外部网络以及内外部联通 实验思路:由易到难,先进行链路聚合、生成树、Vlan、DHCP和单臂路由,然后在进行NAT和ACL的实现,然后用 静态路由实现内外网联通,最后配置外网OSPF协议以及远程登录。 实验步骤 一、链路聚合、生成树 要注意的是链路聚合在两台交换机上都要声明才有效 生成树根的选举一种方法是改变优先级,还有一种方法是直接进行stp根桥的声明stp root priority 二、Vlan Vlan的配置分为三步走,第一步是创建Valn,第二部是确认链路类型,第三步是放行Vlan 三、单臂路由 单臂路由和Vlanif一样,都是为了实现Vlan间的通信,单臂路由通过子接口的方法来实现,这种方案并不会让交换机作为三层设备进行工作,而似乎是把所有的事情都交给路由器进行管理。用户也只要进行单臂路由子接口的划分和网段与vid的声明就可以 四、DHCP DHCP就像他所能做的事情一样,配置时网段、掩码、网关、dns都要进行配置,如果愿意在黑色命令框而不是可视化窗口上敲上这些内容,那DHCP会让ip地址的获取全自动化。 五、NAT和ACL 这两种技术一种可以转化地址来解决外界不认识内部的问题,另一种可以为通行提供保障,让网络链路更加规范化,二者配合可以实现对外网的访问,而他最大的优势是在于二者对于隐私的重视得到保障,无需用十分亲密的OSPF进行连接就可以互相访问。 在这里我犯了一个错误,导致主机ping不通外网,在我检查了网关和路由器的连通性之后,我才意识到了问题可能是出在NAT和ACL的配置上——地址可以到达网关,但出不去,最后证实了这种错误是由于我把NAT与ACL的连接做在了错误的端口上(应该是在出端口,但是我配置到了另一个端口) 六、OSPF 本实验的OSPF是以3号和6号路由为临界的三个自治系统,所以一共需要三个OSPF进程,处于边境的路由器需要有两个ospf routing id 在这里有一个错误出现了,在用import-route ospf* 进行路由引入之后,我发现这三个自治系统并没有完全学习,根据排查,问题出在第三个系统上,在查看了邻居表之后才发现是6号和7号的连接没有建立 七、静态路由和远程登录

pt-archive使用

归档,在 MySQL 中,是一个相对高频的操作。 它通常涉及以下两个动作: 迁移。将数据从业务实例迁移到归档实例。删除。从业务实例中删除已迁移的数据。 在处理类似需求时,都是开发童鞋提单给 DBA,由 DBA 来处理。 于是,很多开发童鞋就好奇,DBA 都是怎么执行归档操作的?归档条件没有索引会锁表吗?安全吗,会不会数据删了,却又没归档成功? 针对这些疑问,下面介绍 MySQL 中的数据归档神器 - pt-archiver。 本文主要包括以下几部分: 什么是 pt-archiver安装简单入门实现原理批量归档不同归档参数之间的速度对比常见用法如何避免主从延迟常用参数 什么是 pt-archiver pt-archiver 是 Percona Toolkit 中的一个工具。 Percona Toolkit 是 Percona 公司提供的一个 MySQL 工具包。工具包里提供了很多实用的 MySQL 管理工具。 譬如,我们常用的表结构变更工具 pt-online-schema-change ,主从数据一致性校验工具 pt-table-checksum 。 毫不夸张地说,熟练使用 Percona Toolkit 是 MySQL DBA 必备的技能之一。 安装 Percona Toolkit 下载地址:Download Percona Toolkit 官方针对多个系统提供了现成的软件包。 我常用的是 Linux - Generic 二进制包。 下面以 Linux - Generic 版本为例,看看它的安装方法。 # cd /usr/local/# wget https://downloads.percona.com/downloads/percona-toolkit/3.3.1/binary/tarball/percona-toolkit-3.3.1_x86_64.tar.gz --no-check-certificate# tar xvf percona-toolkit-3.

使用GDB+QEMU调试Cosmos内核代码

1. 生成带调试符号的elf文件 修改编译选项: GCC 的-O2参数要修改成O0 -g参数:-O0是告诉 GCC 编译器,在编译时不要对代码做优化,这么做可以避免在 GDB 调试时源码和实际程序对应不上的问题;-g参数是为了告诉编译器带上调试符号。 使用grep命令查找需要修改的文件,使用sed命令批量替换,命令如下: grep -i '\-o2' -r //-i 代表不区分大小写 sed -i 's/-O2/-O0 -g/' ./initldr/build/krnlbuidcmd.mh ./script/krnlbuidcmd.S sed -i 's/-Os/-O0 -g/' ./initldr/build/krnlbuidcmd.mh ./script/krnlbuidcmd.S 去掉 ld 的-s参数:-s是告诉 ld 程序链接时去掉所有符号信息,其中包括了调试符号。 grep '\-s ' -r 使用 sed 命令批量去掉 ld 的-s参数,命令如下: sed -i 's/-s / /g' ./initldr/build/krnlbuidcmd.mh ./script/krnlbuidcmd.S 编译生成“带调试符号的 elf 文件" 执行make就可以编译出带有调试符号的 elf 文件,如下图:这里的“not stripped”就表示文件带有调试符号。 Cosmos.elf:当需要调试“内核代码”时,可以在 GDB 中执行symbol-file ./build/Cosmos.elf加载调试符号initldrkrl.elf:当需要调试“二级加载器代码”时,可以在 GDB 中执行symbol-file ./initldr/build/initldrkrl.elf加载调试符号。 制作 hd.img, 用于QEMU运行Cosmos内核 打包生成内核映像文件Cosmos.eki 将要打包的文件copy到同一个文件夹下,执行下列命令:

[暑假] 解决:后端swagger可以正常得到数据,前端接口正确,但是没有得到数据

我遇到的情况是这样的: 后端swagger可以正常查询到数据, 前端接口正确,但是没有得到数据. 然后我试图打印从后端获取到的数据, 发现打印结果为 undefined 这时候要考虑的就是,我们是以什么类型接收 这个是以数组类型接收数据,但是后端传来的是一个对象,所以代码 rows[0]则会打印undefined ==>应该更改成 最下方 rows即可

创建运行nnunet的docker镜像,并且使用nnunet训练自己的2D数据

创建运行nnunet的docker镜像,并且使用nnunet训练自己的2D数据 文档参考链接 nnUNet被广泛的用于各种比赛,并且占据了各大比赛的排行榜。 使用docker 运行nnUNet,有以下好处 docker提供了一个独立的环境,当使用公用服务器的时候或者自己在跑多组环境的对比实验时,不用担心其他环境污染自己的环境 一、安装nvidia-docker 首先已经安装好了新的显卡驱动 安装最新的docker和nvidia-docker $sudo apt-get update $sudo apt-get install docker.io # 启动Docker systemctl start docker # 设置开机自启 systemctl enable docker 使用docker拉取pytorch在GPU中运行的环境 docker pull pytorch/pytorch:latest 从nnUNet官网下载最新的代码 nnUNetgithub地址 进入nnUNet代码文件夹,创建空的Dockerfile文件 二、编辑nnUNet docker 在Dockerfile中复制如下内容 FROM pytorch/pytorch:latest RUN apt-get update && apt-get install -y vim \ && apt-get install -y --no-install-recommends \ python3-pip \ python3-setuptools \ build-essential \ && \ apt-get clean && \ python -m pip install --upgrade pip WORKDIR /workspace COPY .

向量叉乘的几何意义及其模的计算

目的:在传统的向量叉乘计算中,常常遇到叉乘。定义为向量。其这个向量方向满足右手定则。它的模大小,一般被忽略。因此推测一下。 向量叉乘定义: 外积(英语:Cross product)又称向量积(英语:Vector product),是对三维空间中的两个向量的二元运算,用符号: × \times ×表示。可以定义为: a → × b → = c → ( 1 ) \overrightarrow{a} \times \overrightarrow{b} = \overrightarrow{c} \space \space \space \space(1) a ×b =c (1) 假设两个向量 a → × b → \overrightarrow{a} \times \overrightarrow{b} a ×b 外积,它的方向为 c → \overrightarrow{c} c 。其方向由右手定则决定。模长等于这两个向量边的平行四边形的面积。 它的定义也可以写成: a → × b → = ∣ a → ∣ ∣ b → ∣ s i n ( θ ) n → ( 2 ) \overrightarrow{a} \times \overrightarrow{b} = |\overrightarrow{a}||\overrightarrow{b}|sin(\theta)\overrightarrow{n} \space \space \space \space(2) a ×b =∣a ∣∣b ∣sin(θ)n (2)

HK32F030MF4P6 SWD管脚功能复用GPIO

由于电暖控制器项目上管脚不够,需要将SWD管脚复用,使用网上购买的JLINK 下载和串口调试特别方便。 应用场景 往往GPIO管脚不够使用,需要将SWD下载管脚复用GPIO功能,需要用到以下设置,下载器需要接上RESET管脚 // TSSOP20 PIN void ALR_SWDtoIO_Init(void) { GPIO_InitTypeDef m_gpio; // 使能IOMUX时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_IOMUX,ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOB, ENABLE); // PD5 as GPIO m_gpio.GPIO_Mode = GPIO_Mode_OUT; m_gpio.GPIO_OType = GPIO_OType_PP; m_gpio.GPIO_Pin = GPIO_Pin_5; m_gpio.GPIO_PuPd = GPIO_PuPd_NOPULL; m_gpio.GPIO_Speed = GPIO_Speed_Level_2; GPIO_IOMUX_ChangePin(IOMUX_PIN2,IOMUX_PD5_SEL_PD5);// TSSOP20 PIN2(PD5) PD5 IO GPIO_Init(GPIOD, &m_gpio); // PB5 as GPIO m_gpio.GPIO_Pin = GPIO_Pin_5; GPIO_IOMUX_ChangePin(IOMUX_PIN11,IOMUX_PB5_SEL_PB5);//TSSOP20PIN11(PD5)PB5 IO GPIO_Init(GPIOB, &m_gpio); } //次延时代码,必须添加,不然会导致下载不稳的风险 static void softWareDelay(void) { uint16_t i; uint16_t j; for(i=0;i<500;i++) { for(j=0;j<1000;j++)

odoo 启动过程中遇到的问题

odoo 启动过程中遇到的问题 错误: ImportError: No module named 'win32service' 解决办法: pip3 install pypiwin32 错误: ImportError: No module named 'PIL' 解决办法: pip3 install Pillow 浏览器访问odoo出现错误: Uncaught TypeError: Cannot read property 'getBoundingClientRect' of undefined (CSS样式错误) 如若出现上面的错误,意味着错误是来自于libsass库,执行如下代码即可: pip3 install libsass 错误: ImportError: No module named psycopg2 解决办法: sudo apt-get install build-dep python-psycopg2 pip3 install psycopg2-binary 错误: ImportError: No module named OpenSSL 解决办法: pip3 install pyOpenSSL 错误 ImportError: cannot import name 'soft_unicode' from 'markupsafe' 解决办法:

laravel配置发送邮件

.env配置 MAIL_MAILER=smtp MAIL_HOST=smtp.exmail.qq.com MAIL_PORT=465 MAIL_USERNAME=你的邮箱 MAIL_PASSWORD=你的邮箱密码或密匙 MAIL_ENCRYPTION=ssl MAIL_FROM_ADDRESS=你的邮箱 MAIL_FROM_NAME=你的邮箱 参数说明 // driver:⽤于配置默认的邮件发送驱动。 // Laravel⽀持多种邮件驱动⽅式,包括smtp、Mailgun、Maildrill、Amazon SES、mail和sendmail; // Mailgun和Amazon SES都是收费的Maildrill⽬前不⽀持中国区⽤户,这三个都是第三⽅邮件服务。 // mail驱动使⽤PHP提供的mail函数发送,sendmail驱动通过Sendmail/Postfix(Linux)提供的命令发送邮件; // smtp驱动通过⽀持ESMTP的SMTP发送邮件。 // 就⽬前状况来看,使⽤smtp是最明智的选择; // mail不安全,sendmail需要安装配置Sendmail/Postfix,其他要么付费要么不能⽤。 // host:邮箱所在主机; // 使⽤163邮箱,对应值是smtp.163.com; // 使⽤QQ邮箱,对应值是smtp.qq.com。 // 使⽤腾讯企业邮箱,对应值是smtp.exmail.qq.com // port:⽤于配置邮箱发送服务端⼝号, // ⼀般默认值是25,但如果设置SMTP使⽤SSL加密,该值为465。 // from:配置项包含address和name, // address 表⽰你⾃⼰的邮箱 // name 表⽰你邮件⽤户名(这⾥邮箱,是⽤来发邮件的邮箱)。 // encryption:表⽰加密类型; // 可以设置为null表⽰不使⽤任何加密,也可以设置为tls或ssl。 // username: 表⽰邮箱账号,⽐如123456789@qq.com 控制器具体使用 可以参考laravel文档 https://learnku.com/docs/laravel/7.x/mail/7488#4dfbb0 use Illuminate\Support\Facades\Mail; //发送邮箱测试 public function sendmail(){ Mail::raw('你好,我是PHP程序!', function ($message) { $to = 'ceshi@qq.com'; $message ->to($to)->subject('纯文本信息邮件测试'); }); }

浅谈四种线程池

转自:微点阅读 https://www.weidianyuedu.com 首先我们先看一下获取四种线程池的代码: ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10); ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10); ExecutorService singleThreadPool = Executors.newSingleThreadExecutor(); 可以发现这四种线程池都是由Executors类生成的。依次点开四个方法的内部实现发现,它们最终调用的都是同一个ThreadPoolExecutor()的构造器,而区别在于构造器的参数不同。我们来看下ThreadPoolExecutor的参数列表: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { 正是由于这几个参数的不同导致了四种线程池的工作机制不同。参考源码对于参数的注释,我们列出参数的含义。 corePoolSize:核心线程数量,常驻在线程池中的线程,即使它们是空闲的,也不会销毁,除非设置allowCoreThreadTimeOut的值。 maximumPoolSize:线程池最大线程数量 keepAliveTime:超过核心数量的额外线程也就是非核心线程,在空闲指定的最大时间后被销毁。(假设时间为5s,核心线程数为2,当前线程为4,则超过核心线程数的其余两个线程在空闲5秒后会被销毁。) unit:时间单位 workQueue:等待队列 threadFactory:生成线程的工厂 handler:当等待队列容量满以及线程池数量达到最大时,如何处理新的任务。 AbortPolicy(默认):直接抛出异常 CallerRunsPolicy:交给调用者所在线程执行。(假设当前调用者线程是Main,那么就交给Main处理) DiscardOldestPolicy:丢弃最久未处理的任务,再执行当前任务。(最久未处理的,在队列中其实就是队列头节点,查看源码的确调用是poll()方法) DiscardPolicy:丢掉该任务,并且不抛异常。 线程池的工作机制: 当持续往线程池添加任务,当前线程数量小于核心线程数量的时候,新增线程。当前线程数量达到核心线程数量的时候,将任务放入等待队列。当等待队列满的时候,继续创建新线程。当线程池数量达到最大并且等待队列也满的时候,采取拒绝服务策略。 接下来我们就根据参数来分析不同的线程池: FixedThreadPool public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } 我们可以看到corePoolSize核心线程数量和maximumPoolSize最大线程数量是一致的,并且keepAliveTime为0。workQueue是LinkedBlockingQueue,这是一个链表阻塞队列。可以得出结论:该线程池是一个固定数量的线程池,并且有一个无界的等待队列。我们可以推导出该线程池适合处理任务量平稳的场景。例如平均一秒接收10个任务,接收任务量曲线不会很陡峭。 适合场景:适合少量的大任务(大任务处理慢,如果线程数量多的话,反而在切换线程上下文时损耗,所以控制线程在一定的数量)。

0基础学MySQL数据库—从小白到大牛(24)存储引擎

文章目录 前言一、查看存储引擎二、设置系统默认的存储引擎三、设置表的存储引擎创建表时指定存储引擎修改表的存储引擎 四、引擎介绍InnoDB 引擎:具备外键支持功能的事务存储引擎MyISAM 引擎:主要的非事务处理存储引擎MyISAM和InnoDBArchive 引擎:用于数据存档Blackhole 引擎:丢弃写操作,读操作会返回空内容CSV 引擎:存储数据时,以逗号分隔各个数据项Memory 引擎:置于内存的表 补充InnoDB表的优势InnoDB和ACID模型InnoDB架构 前言 本章开始使用的测试数据库为GreatSQL8.0.25版本 (Wed Aug 3 16:17:03 2022)[root@GreatSQL][(none)]>select version(); +-----------+ | version() | +-----------+ | 8.0.25-16 | +-----------+ 1 row in set (0.00 sec) 为了管理方便,人们把连接管理、查询缓存、语法解析、查询优化这些并不涉及真实数据存储的功能划分为MySQL server的功能,把真实存取数据的功能划分为存储引擎的功能。所以在MySQL server完成了查询优化后,只需按照生成的执行计划调用底层存储引擎提供的API,获取到数据后返回给客户端就好了。 MySQL中提到了存储引擎的概念。简而言之,存储引擎就是指表的类型。其实存储引擎以前叫做表处理器,后来改名为存储引擎,它的功能就是接收上层传下来的指令,然后对表中的数据进行提取或写入操作。 一、查看存储引擎 查看mysql提供什么存储引擎: (Fri Aug 5 11:28:25 2022)[root@GreatSQL][(none)]>show engines; +--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+ | Engine | Support | Comment | Transactions | XA | Savepoints | +--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+ | FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL | | PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO | | InnoDB | DEFAULT | Percona-XtraDB, Supports transactions, row-level locking, and foreign keys | YES | YES | YES | | MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO | | MyISAM | YES | MyISAM storage engine | NO | NO | NO | | MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO | | BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO | | CSV | YES | CSV storage engine | NO | NO | NO | | ARCHIVE | YES | Archive storage engine | NO | NO | NO | +--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+ 9 rows in set (0.

遥遥领先一键导出微信小程序、UNIAPP低代码源码使用介绍

1.1添加组件至设计器 在左侧基本组件库选择要使用的组件,按住左键不放,拖动到设计器适合的位置上松开。 1.2修改组件图层名称 修改组件图层名称,方便快速定位组件位置。找到图层面板按钮,点击显示图层面板,图层面板将会显示当前所有的组件。 1.3修改组件字段标识 字体标识是用来区分组件的标识,尽量保持维一性,在不改变的组件标识的情况下,每拖动一次相同组件,组件标识会自动增加1,组件标识在实际使用中会根据组件特性来起效。 比如有两个字段用户名及密码,那么组件字段标识username、password。 1.2 修改组件栅格大小 通过基础的 24 分栏,迅速简便地创建布局。快速拖动栅格大小,改变布局,方便快速页面排版。 基础排版都可以直接采用栅格大小来布局,复杂的布局将会借助容器组件里FLEX组件来达到复杂的布局。 1.5. 修改图层布局 Ø 设计区拖动 在设计区找到想要变更位置组件,按住鼠标左键,即可快速变换位置。 Ø 图层区拖动 重点推荐图层区拖动,特别在复杂的布局下,通过移动组件图层的顺序来达到变更布局,达到比较精细化拖动效果。 1.6. 修改组件个数 宫格组件、图文菜单、图片轮播、组件轮播、选项卡、折叠面板等组件默认数组,支持增加、修改、删除、改变顺序。 以宫格组件为例,组件默认个数为6,移动组件对应内容区,点击对应功能按钮图标动态改变组件。 1.7. 修改组件样式 1.7.1. 基础设置 设置字体颜色、大小、是否粗体、是否斜体、文本划线等。 1.7.2. 背景设置 背景内置了背景颜色库、也支持自定义背景图片、渐变背景等,其中背景图片设置背景图片位置、图片显示方式、背景重复。 默认第一个背景颜色有为系统内置背景库。系统已经内置了常用一些背景库,可以直接使用。 如果对内置的背景库不满意,用户根据根据的要求来设计背景。 Ø 背景图片 在线自定义背景图片或直接输入图片地址。下图使用自定义背景图片及填充方式,其中填充方式在实际效果中因为图片不同会起到不同效果。 Ø 渐变背景 在线自定义渐变背景或直接输入渐变样式 Ø 背景颜色 自定义背景颜色,支持透明背景颜色 1.7.3. 外边距设置 通过使用单独的外边距属性,可以对上、右、下、左的外边距进行设置。即: margin-top、margin-right、 margin-bottom、 margin-left。 设置外边距开关:只有开关启用,才起效。 ² 负值设置 外边距支持负值设置,在一些特殊场景里,使用负值来设计能达到更好的效果。 Ø 组件交叉显示 Ø **上方组件圆角效果显示 1.7.4. 内边距设置 通过使用单独的内边距属性,可以对上、右、下、左的内边距进行设置。即: padding-top、padding-right、 padding-bottom、 padding-left。 设置内边距开关:只有开关启用,才起效。 内边距设置右内边距在默认情况下,比如文本组件内边距内容又比较少的情况下效果不明显,是因为默认文本组件占比是100%,需要把组件栅格大小至0,效果比较好。比如下图实际应用效果。 1.7.5. 圆角设置 通过使用单独的圆角属性,可以对上左、上右、下左、下右的四个圆角进行设置。即: border-top-left-radius、border-top-right-radius、border-bottom-left-radius、border-bottom-right-radius。