VxWorks程序指南
*******************************************
一、任务
*******************************************
任务状态:挂起、阻塞、就绪、睡眠。
任务可以在任何一种状态被删除。
Wind内核里有256种优先级,0最高,255为最低。
任务调度控制函数
kernelTimeSlice() 控制轮转调度
taskPrioritySet() 改变任务优先级
taskLock() 禁止任务调度
taskUnlock() 允许任务调度
当任务访问一个可能会被中断服务程序访问的变量或者数据结构时,可以使用intLock()实现互斥。
通过taskLock()、taskUnlock()抢占上锁可禁止优先级的抢占,中断服务程序仍然可以执行。
所有应用任务的优先级应该在100-250之间;但是驱动程序支持的任务(与中断服务程序关联的任务)优先级能够位于51-99。
任务堆栈的空间分配:为了避免堆栈溢出和破坏任务堆栈可使用下列方法:
在最初分配堆栈空间时,分配比预先估计大一些的空间;然后周期性地调用checkStack()函数监控;若可以安全使用更小的空间,将修改分配空间的尺寸。
一般vxWorks使用任务ID号来定位任务,约定ID号为0的表示任务调用。
vxWorks操作系统不需要惟一的任务名,但为了避免混乱,建议使用惟一的任务名。
vxWorks操作系统的任务命名规则:所有从目标机启动的任务以字母t开头,而从主机启动的任务以字母u开头。
任务创建函数
taskSpawn() 创建并激活一个新任务
taskInit() 初始化一个新任务
taskActivate()激活一个初始化任务
任务名和ID函数
taskName() 得到与任务号相关的任务名
taskNameToId()寻找与任务名相关的任务ID
taskIdSelf() 获得调用任务的ID号
taskIdVerify()检查一个特定任务的存在性
在任务创建时,若需执行下列操作则要包括VX_FP_TASK选项:
1实行浮点操作2调用返回浮点值的函数3调用以浮点值为参数的函数
任务选项函数
taskOptionGet() 检查任务选项
taskOptionSet() 设置任务选项 目前只有VX_UNBREAKABLE选项可以被修改
任务信息:由于任务状态是动态的,除非知道任务处于挂起,否则不能获得当前信息
taskIdListGet() 用ID填充一组所有激活的任务
taskInfoGet() 得到任务的信息
taskPriorityGet() 查看任务的优先级
taskRegsGet() 检查任务寄存器(不能使用单前任务时)
taskRegsSet() 设置任务寄存器(不能使用单前任务时)
taskIsSuspended()检查任务是否处于挂起状态
taskIsReady() 检查任务是否处于就绪状态
taskTcb() 获得任务控制块的指针
任务删除函数
exit() 终止任务调用,释放内存
taskDelete()终止指定任务,释放内存
taskSafe() 保护调用任务免于删除
taskUnsafe() 解除任务删除保护
下面的代码表明了如何使用taskSafe()函数和taskUnsafe()函数去保护一个临界代码区域
taskSafe();
semTake (semId,WAIT_FOREVER);/*阻塞直至信号量可用*/
.../*临界区域代码*/
semGive(semId); /*释放信号量*/
taskUnsafe();
任务控制函数
taskSuspend() 挂起任务,用来冻结任务状态并进行检查
taskResume() 恢复任务执行
taskRestart() 重新启动任务
taskDelay() 延迟任务,延迟单位为“tick”
nanosleep() 延迟任务,延迟单位为纳秒
下面的代码无需考虑时钟速率,将使任务延时半秒:
taskDelay(sysClkRateGet()/2);/*函数sysClkRateGet()返回系统时钟的速率,单位tick/秒*/
taskDelay()函数把作为调用者的任务移动到相同优先级队列的尾部。
特别是,当调用taskDelay(0)时,将会把CPU交给系统中其他相同优先级任务。
taskDelay(NO_WAIT);/*允许其他相同优先级的任务运行*/
延时为零时,只能调用taskDelay()函数,函数nanosleep()中的延时参数禁止为零。
任务扩展函数
为了允许其他相关的任务函数加入到系统中去,vxWorks提供“hook”函数。该函数允许任务在创建
、删除和上下文交换时调用附加的函数。
taskCreateHookAdd() 增加一个在每个任务创建时都调用的函数
taskCreateHookDelete() 删除一个以前加入的任务创建函数
taskSwitchHookAdd() 增加一个在每个任务切换时都调用的函数
taskSwitchHookDelete() 删除一个以前加入的任务切换函数
taskDeleteHookAdd() 增加一个在每个任务被删除时都调用的函数
taskDeleteHookDelete() 删除一个以前加入的任务删除函数
*******************************************
二、任务通信
*******************************************
大部分vxWorks函数使用下列重入技术:1动态堆栈变量2被信号保护的全局和静态变量2任务变量
在编写被多个任务内务调用的应用代码时,建议使用这些技术。
vxWorks的任务间通信:
1共享内存,数据的简单共享
2信号量,基本的互斥和同步
3Mutexe和条件变量,使用POSIX接口时互斥与同步操作
4消息队列和管道,同一个CPU内任务间消息的传递
5sockets和远程任务调用,任务间透明的网络通信
6信号,用于异常处理。
信号量控制函数
semBCreate() 分配并初始化一个二进制信号量
semMCreate() 分配并初始化一个互斥信号量
semCCreate() 分配并初始化一个计数器信号量
semDelete() 终止并释放一个信号量
semTake() 获取一个信号量
semGive() 提供一个信号量
semFlush() 解锁所有正在等待信号量的任务
二进制信号量
使用二进制信号量能够满足两种任务的协调需要:互斥和同步。
互斥的实现:
创建一个二进制信号量,初始可用(SEM_FULL)。
当任务访问资源时,首先必须获得信号量。
只要任务持有信号量,其他所有需要访问该资源的任务将被阻塞。
#include "vxWorks.h"
#include "semLib.h"
SEM_ID semMutex;
semMutex = semBCreate(SEM_Q_PRIORITY,SEM_FULL);
...
semTake (semMutex,WAIT_FOREVER);
.../*临界区域,任何时候仅单个任务可以访问*/
semGive(semMutex);
同步的实现:
初始时信号量不可用(SEM_EMPTY)。
任务或中断服务程序通过释放信号量来表明事件的发生。
调用semTake()函数提取信号量的其他任务处于等待状态,直至事件发生,并释放信号量。
#include "vxWorks.h"
#include "semLib.h"
#include "arch/arch/ivarch.h"/*用结构体类型代替arch*/
SEM_ID syncSem;
init(int someIntNum)
{
/*连接中断服务函数*/
intConnect(INUM_TO_IVEC(someIntNum),evertInterruptSvcRout,0);
/*建立信号量*/
syncSem = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
/*发起用于同步的任务*/
taskSpawn("sample",100,0,20000,task1,0,0,0,0,0,0,0,0,0,0);
}
task1(void)
{
...
semTake(syncSem, WAIT_FOREVER);/*等待事件发生*/
printf("task 1 got the semaphore\n");
.../*启动事件*/
}
eventInterruptSvcRout(void)
{
...
semGive(syncSem);/*让任务1启动事件*/
...
}
互斥信号量:
互斥信号量是一种用于解决内在互斥问题的特殊的二进制信号量,包括优先级倒置,删除安区以及资源的递归访问。
互斥信号量的基本行为与二进制信号量一致,不同之处如下:
1它仅用于互斥2它仅能由提取它(即调用semTake())的任务释放3不能在中断服务程序中释放4semFlush()函数操作非法。
当一个高优先级任务需要等待一段不确定的时间,让低优先级任务完成时(如低优先级通过信号量占有高优先级任务需要的资源),
需要发生优先级倒置。
下例用优先级继承算法创建了一个互斥信号量:
semId = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);/*使用优先级继承选项SEM_INVERSION_SAFE的信号量必须选择优先级顺序队列*/
下例是为防止应用临界资源的任务被意外删除的一个互斥信号量
semId = semMCreate(SEM_Q_FIFO | SEM_DELETE_SAFE);
计数信号量应用:计数信号量适用于保护多份复制的资源:如可以使用一个初始值为5的计数器信号量来协调5个磁带驱动器工作。
Wind消息队列控制
msgQCreate() 分配并初始化一个消息队列
msgQDelete() 终止并释放一个消息队列
msgQSend() 向一个消息队列发送消息
msgQReceive() 从一个消息队列接收消息
/* In this example, task t1 creates the message queue and sends a message
* to task t2. Task t2 receives the message from the queue and simply
* displays the message.
*/
/* includes */
#include "vxWorks.h"
#include "msgQLib.h"
/* defines */
#define MAX_MSGS (10)
#define MAX_MSG_LEN (100)
MSG_Q_ID myMsgQId;
task2 (void)
{
char msgBuf[MAX_MSG_LEN];
/* get message from queue; if necessary wait until msg is available */
if (msgQReceive(myMsgQId, msgBuf, MAX_MSG_LEN, WAIT_FOREVER) == ERROR)
return (ERROR);
/* display message */
printf ("Message from task 1:\n%s\n", msgBuf);
}
#define MESSAGE "Greetings from Task 1"
task1 (void)
{
/* create message queue */
if ((myMsgQId = msgQCreate (MAX_MSGS, MAX_MSG_LEN, MSG_Q_PRIORITY))
== NULL)
return (ERROR);
/* send a normal priority message, blocking if queue is full */
if (msgQSend (myMsgQId, MESSAGE, sizeof (MESSAGE), WAIT_FOREVER,
MSG_PRI_NORMAL) == ERROR)
return (ERROR);
}
实时系统经常构造成任务的客户机/服务器使用模式。
vxWorks事件是一种在任务和中断处理程序间,或任务和vxWorks结构体间的通信方式。
看门狗定时器函数调用
wdCreate() 分配并初始化一个看门狗定时器
wdDelete() 终止并释放一个看门狗定时器
wdStart() 启动一个看门狗定时器
wdCancel() 取消当前的一个技术的看门狗定时器
/* Creates a watchdog timer and sets it to go off in 3 seconds.*/
/* includes */
#include "vxWorks.h"
#include "logLib.h"
#include "wdLib.h"
/* defines */
#define SECONDS (3)
WDOG_ID myWatchDogId;
task (void)
{
/* Create watchdog */
if ((myWatchDogId = wdCreate( )) == NULL)
return (ERROR);
/* Set timer to go off in SECONDS - printing a message to stdout */
if (wdStart (myWatchDogId, sysClkRateGet( ) * SECONDS, logMsg,
"Watchdog timer just expired\n") == ERROR)
return (ERROR);
/* ... */
}
*******************************************
三、中断
*******************************************
中断处理函数
intConnect() 设置中断处理的C程序
intContext() 如果是从中断级调用,返回真
intCount() 获得当前中断嵌套深度
intLevelSet(() 设置处理器的中断屏蔽级
intLock() 禁止中断
intUnlock() 重新允许中断
intVecBaseSet() 设置向量基地址
intVecBaseGet() 得到向量基地址
intVecSet() 设置异常向量
intVecGet() 获得异常向量
中断服务程序禁止调用浮点协处理器函数。因为由intConnect()函数建立的中断驱动代码不能保存和恢复浮点寄存器。
*******************************************
四、输入/输出系统(1)
*******************************************
文件描述符(fd)的默认值:0=标准输入设备 1=标准输出设备 2=标准错误输出设备
下例将调用此函数的任务(ID = 表示该任务本身)标准输出文件(fd =1 )重定向到一个已打开的文件(fd = fileFd).
ioTaskStdSet(0,1,fileFd);
fd = open("name",flags,mode);
文件访问方式标志(flags)
O_RDONLY 0(hex) 以只读方式打开文件
O_WRONLY 1(hex) 以只写方式打开文件
O_RDWR 2(hex) 以读写方式打开文件
O_CREAT 200(hex)建立一个新文件
O_TRUNC 400(hex)删除该文件
基于多文件描述符的挂起操作:选择功能The Select Facility
选择功能中的宏函数
FD_ZERO 将所有标志位设置为“0”
FD_SET 对指定文件描述符的标志位设置为“1”
FD_CLR 对指定文件描述符的标志位设置为"0"
FD_ISSET 如果指定标志位值为“1”,则返回“1”;否则返回“0”
/* selServer.c - select example
* In this example, a server task uses two pipes: one for normal-priority
* requests, the other for high-priority requests. The server opens both
* pipes and blocks while waiting for data to be available in at least one
* of the pipes.
*/
#include "vxWorks.h"
#include "selectLib.h"
#include "fcntl.h"
#define MAX_FDS 2
#define MAX_DATA 1024
#define PIPEHI "/pipe/highPriority"
#define PIPENORM "/pipe/normalPriority"
/************************************************************************
* selServer - reads data as it becomes available from two different pipes
*
* Opens two pipe fds, reading from whichever becomes available. The
* server code assumes the pipes have been created from either another
* task or the shell. To test this code from the shell do the following:
* -> ld < selServer.o
* -> pipeDevCreate ("/pipe/highPriority", 5, 1024)
* -> pipeDevCreate ("/pipe/normalPriority", 5, 1024)
* -> fdHi = open ("/pipe/highPriority", 1, 0)
* -> fdNorm = open ("/pipe/normalPriority", 1, 0)
* -> iosFdShow
* -> sp selServer
* -> i
* At this point you should see selServer's state as pended. You can now
* write to either pipe to make the selServer display your message.
* -> write fdNorm, "Howdy", 6
* -> write fdHi, "Urgent", 7
*/
STATUS selServer (void)
{
struct fd_set readFds; /* bit mask of fds to read from */
int fds[MAX_FDS]; /* array of fds on which to pend */
int width; /* number of fds on which to pend */
int i; /* index for fd array */
char buffer[MAX_DATA]; /* buffer for data that is read */
/* open file descriptors */
if ((fds[0] = open (PIPEHI, O_RDONLY, 0)) == ERROR)
{
close (fds[0]);
return (ERROR);
}
if ((fds[1] = open (PIPENORM, O_RDONLY, 0)) == ERROR)
{
close (fds[0]);
close (fds[1]);
return (ERROR);
}
/* loop forever reading data and servicing clients */
FOREVER
{
/* clear bits in read bit mask */
FD_ZERO (&readFds);
/* initialize bit mask */
FD_SET (fds[0], &readFds);
FD_SET (fds[1], &readFds);
width = (fds[0] > fds[1]) ? fds[0] : fds[1];
width++;
/* pend, waiting for one or more fds to become ready */
if (select (width, &readFds, NULL, NULL, NULL) == ERROR)
{
close (fds[0]);
close (fds[1]);
return (ERROR);
}
/* step through array and read from fds that are ready */
for (i=0; i< MAX_FDS; i++)
{
/* check if this fd has data to read */
if (FD_ISSET (fds[i], &readFds))
{
/* typically read from fd now that it is ready */
read (fds[i], buffer, MAX_DATA);
/* normally service request, for this example print it */
printf ("SELSERVER Reading from %s: %s\n",
(i == 0) ? PIPEHI : PIPENORM, buffer);
}
}
}
}
*******************************************
四、输入/输出系统(2)
*******************************************
异步输入输出操作(AIO)
能够在执行普通的内部处理时,同时执行输入/输出操作。
异步输入输出操作函数
aioPxLibInit() 初始化AIO功能函数库
aioShow() 显示AIO功能要求
aio_read() 初始化异步读操作
aio_write() 初始化异步写操作
aio_listio() 初始化个数最多为LIO_MAX的AIO功能请求
aio_error() 在一个AIO操作中寻找错误状态值
aio_return() 在一个已完成的AIO操作中寻找返回状态值
aio_cancel() 取消一个AIO操作
aio_suspend() 等待一个AIO操作完成、被中断或超时
vxWorks操作系统中的驱动程序
ttyDrv 终端设备驱动程序
ptyDrv 伪终端设备驱动程序
pipeDrv 管道设备驱动程序
memDrv 伪存储设备驱动程序
nfsDrv NFS系统客户机驱动程序
netDrv 用于远程文件访问的网络驱动程序
ramDrv 用于创建RAM存储盘的RAM驱动程序
scsiLib SCSI接口库
串行I/O设备(终端和伪终端设备)
vxWorks操作系统中的I/O设备是一种缓冲型的串行字节流设备。每个设备都有一个环形缓冲区用于输入和输出操作。
下例是在tty设备上设置除了OPT_MON_TRAP功能外的所有功能;
status = ioctl (fd, FIOSETOPTIONS, OPT_TERMINAL & ~OPT_MON_TRAP);
tty设备的可选项
OPT_LINE 选择线形传输模式
OPT_ECHO 向同一输出通道回应输入的字符
OPT_CRMOD 将输入的RETURN字符翻译成NEWLINE标志;将输出的NEWLINE标志翻译成RETURN-LINEFEED字符
OPT_TANDEM 响应软件流量控制字符CTRL+Q和CTRL+S(XON and XOFF)
OPT_7_BIT 从所有输入字节中取出最高位
OPT_MON_TRAP 使特殊ROM软中断监控程序字符有效,默认为CTRL+X
OPT_ABORT 使特殊目标机SHELL程序终止字符,默认为CTRL+Z
OPT_TERMINAL 将上述选项位设为“1”
OPT_RAW 不设置上述选项位
tyLib文件支持的I/O操作控制函数
FIOBAUDTATE 对指定参数设置传输速率
FIOCANCEL 取消一次读/写操作
FIOFLUSH 丢弃输入和输出缓冲区中的所有数据
FIOGETNAME 获取指定文件描述符对应的文件名
FIOGETOPTIONS 返回当前设备选项字内容
FIONREAD 获取输入缓冲区中的未读字节数
FIONWRITE 获取输出缓冲区中的字节数
FIOSETOPTIONS 设置设备选项字的内容
管道设备
一个任务可以向管道写信息,其他任务可以读取这些信息。
创建管道设备
status = pipeDevCreate("/pipe/name",maxMsgs, maxLength);
pipeDrv文件支持的I/O操作控制函数
FIOFLUSH 丢弃管道中所有信息
FIOGETNAME 获取指定文件描述符对应的管道名
FIONMSGS 获取管道中的信息数目
FIONREAD 获取管道中第一条信息的字节数
伪存储设备(memDrv)
memDrv驱动程序允许I/O系统访问存储器像访问伪I/O设备一样。
memDrv文件支持的I/O操作控制函数
FIOSEEK 在文件中设置当前字节偏移量
FIOWHERE 返回当前在文件中的位置
网络文件系统(NFS)设备
网络文件系统设备可以通过NFS协议存取远程主机上的文件。
下例函数在主机"mars"中安装名为“/usr”的系统,本地系统名为“/vxusr”。
nfsMount("mars","/usr","/vxusr");
nfsDrv文件支持的I/O控制函数
FIOFSTATGET 获取文件状态信息
FIOGETNAME 获取指定文件描述符对应的文件名
FIONREAD 获取文件中未读取字节数
FIOREADDIR 读取下一个目录入口信息
FIOSEEK 在文件中设置当前字节偏移量
FIOSYNC 向远程NFS文件刷新数据
FIOWHERE 返回文件中当前字节偏移量
非NFS网络设备
利用远程外壳协议(RSH)或文件传输协议(FTP)访问远程主机上的文件。这些网络设备需要netDrv驱动程序支持。
I/O系统的功能是将用户的I/O请求与相应驱动程序中的相应操作函数相连。I/O系统通过维护一个包括每个驱动程序中每个操作函数的地址表来完成上述工作。
drvnum = iosDrvInstall(xxCreat,0,xxOpen,0,xxRead,xxWrite,xxIoctl);
块存取设备
块存取设备的驱动程序不是与I/O系统直接相连,而是与文件系统相互作用,文件系统再与I/O系统相连.
块存取设备驱动程序中通用的操作包括:
1初始化硬件2分配并初始化数据结构3建立信号量4初始化中断向量5允许中断操作
文件系统将自己作为驱动程序装入驱动程序表中,并且通过使用存放于块存取设备结构BLK_DEV(直接访问的块存取设备)或SEQ_DEV(顺序访问的块存取设备)中的函数地址调用实际的驱动程序。
驱动程序支持库(对用户编写驱动程序有帮助)
errnoLib 错误状态函数库
ftpLib ARPA文件传输协议函数库
ioLib I/O接口函数库
iosLib I/O系统函数库
intLib 中断支持函数库
remLib 远程命令函数库
rngLib 环形缓冲区子程序函数库
ttyDrv 终端驱动程序函数库
wdLib 看门狗定时器函数库
*******************************************
五、本地文件系统
*******************************************
dosFs文件系统:适用于块存取设备(磁盘)的实时操作,与MS-DOS文件系统兼容;
rawFs文件系统:提供了一种简单的原始文件系统。该文件系统将整个磁盘当作一个单独的大文件;
tapeFs文件系统: 适用于不使用标准文件或目录结构的磁带设备。实际上将磁带盘当作一个原始设备并将整个磁带盘当作一个大文件;
cdromFs文件系统:允许应用程序从按照ISO9660标准文件系统格式化的CD-ROM设备上读取数据;
TSFS目标服务器文件系统:通过使用Tornado软件中的目标服务器,使得目标机可以访问主机系统的文件。
VxWorks程序指南的更多相关文章
- [原创] NetBean开发c++程序指南1- 加入c++项目文件夹
利用 NetBean开发c/c++程序,导入原有程序代码. 1. 在菜单栏的 "工具" -> 选项 -> c/c++开发 如果彩色就是激活的状态,否则选择激活. 2. ...
- 使用VS Code 开发.NET CORE 程序指南
1. 前言 近两年来,很多前端的同学都开始将 VSCode 作为前端主力开发工具,其丰富的扩展给程序开发尤其是前端开发带来了很多便利,但是作为微软主力语言的 .NET,却由于有宇宙第一编辑器 Visu ...
- 微信小程序学习指南
作者:初雪链接:https://www.zhihu.com/question/50907897/answer/128494332来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- 基于嵌入式操作系统VxWorks的多任务并发程序设计(1)――基本概念
1引言 嵌入式系统定义义为:嵌入到对象体系中的专用计算机系统."嵌入性"."专用性"与"计算机系统"是嵌入式统的三个基本要素,对象系统则是指 ...
- 基于嵌入式操作系统VxWorks的多任务并发程序设计(2) ――任务控制
4 任务与任务状态 VxWorks实时内核Wind提供了基本的多任务环境.对用户而言,宏观上看起来,多个任务同时在执行.而本质而言,在微观上,系统内核中的任务调度器总是在根据特定的调度策略让它们交替运 ...
- VxWorks 符号表
符号表初始化 符号表用于建立符号名称.类型和值之间的关系.其中,名称为null结尾的任意字符串:类型为标识各种符号的整数:值为一个字符指针.符号表主要用来作为目标模块加载的基础,但 ...
- 微信小程序开发学习资料
作者:初雪链接:https://www.zhihu.com/question/50907897/answer/128494332来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- 译:微软发布.NET应用架构指南草案
原文<Microsoft Announces Draft .NET Architecture Guidance> 译注:上周微软发布了全新的<.NET应用架构指南>草案,以征求 ...
- asp.net core系列 71 Web架构分层指南
一.概述 本章Web架构分层指南,参考了“Microsoft应用程序体系结构指南”(该书是在2009年出版的,当时出版是为了帮助开发人员和架构师更快速,更低风险地使用Microsoft平台和.NET ...
随机推荐
- FBReader阅读引擎支持的功能
"三十年河东,三十年河西"是一句民间谚语,它的来源是:从前黄河河道不固定,经常会改道(历史上无数次发生).某个地方原来在河的东面,若干年后,因黄河水流改道,这个地方会变为在河的西面 ...
- Audio Unit 基础
如图所示,所有 iOS 音频技术都是基于 audio units.此处显示的更高级别的技术,如 Media Player,AV Foundation,OpenAL,AudioToolbox,是对 au ...
- 前段篇:HTML
<!DOCTYPE html> 文件开头统一的标准! HTML包含了两部分: head与body 固定的格式. 一.head部分: head部分分为两部分:meta标签与非meta标签: ...
- verilog实验2:基于FPGA的59秒计时器设计
一.实验任务 利用四个数码管显示59秒计时器. 二.代码实现 将开发板的48M晶振分频出1M,然后计数器累加,将计数器结果显示在数码管上.低位逢十进一,第二位逢五进一,依次构成59秒计时器. 部分代码 ...
- FTP工具
上传本地资源到FTP服务器,可以使用LeapFTP软件.左侧为本地资源,右侧为FTP资源.输入用户名,密码,连接后直接拖动即可. 为本地资源建立FTP,可以方便进行设备升级.文件传输等.
- Codeforces Round #410 (Div. 2)
Codeforces Round #410 (Div. 2) A B略..A没判本来就是回文WA了一次gg C.Mike and gcd problem 题意:一个序列每次可以把\(a_i, a_{i ...
- spring security 4 filter 顺序及作用
Spring Security 有两个作用:认证和授权 一.Srping security 4 filter 别名及顺序 spring security 4 标准filter别名和顺序,因为经常要用就 ...
- JS原型学习之旅(一)之一图了解原型链关系
目前正在学JS的原型思想(准确的说是从昨天2018.1.29开始正式接触),琢磨了两天,在chrome的console不停的敲了好多代码测试__proto__和prototype的关系,有了些小收获( ...
- 写好Java代码的30条经验总结(转)
成为一个优秀的Java程序员,有着良好的代码编写习惯是必不可少的.下面就让我们来看看代码编写的30条建议吧. (1) 类名首字母应该大写.字段.方法以及对象(句柄)的首字母应小写.对于所有标识符,其中 ...
- Spring_Spring与DAO_Spring的Jdbc模板
一.导入Jar包 二.定义实体类与DB表 public class Student { private Integer id; private String name; private int age ...