一.设计测试用的数据库
1.新建数据库
create database testmysql;
2.新建一个用户信息数据表
create table test(
username varchar(20) primary key,
password varchar(20));
3.给新表插入数据信息
insert into test values('keivn','123456');
二. 设计局部数据源和连接池
1.在webapps目录中新建test目录,然后在test中分别新建WEB-INF和META-INF目录,在WEB-INF目录
中新建classes和lib目录,将mysql数据库驱动文.jar放进lib目录中
这里我使用的版本是mysql-connector-java-5.1.22-bin.jar
2.在META-INF目录中新建context.xml文件,然后将下面内容复制,保存
<?xml version='1.0' encoding='utf-8'?>
<Context>
<Resource name="jdbc/mysql"
auth="Container"
driverClassName="com.mysql.jdbc.Driver"
type="javax.sql.DataSource"
url="jdbc:mysql://localhost:3306/testmysql"
username="root"
password="123456"
maxActive="100"
maxIdle="30"
maxWait="10000" />
</Context>
context.xml中的参数的解析如下:
name属性是数据源名称,通常采取jdbc/**.
type属性是数据源方式。
driverClassName属性是驱动程序名称。
username,password,数据库名称和密码
url:访问的数据库路径。
maxActive属性是并发连接的最大数。设置为0则无限制。
maxWait属性是等待连接的最大连接的时间。
maxIdle属性是连接池中空闲的连接的个数。
上文中的设置的 maxActive="100"说明可以最大连接的个数为100个,再建立连接,则出现异常。
而maxIdle="30"说明当关闭数据库时(不是真正的断开连接,而是归还连接池中)连接池中最大可以有空闲的连接数为30个。
若是再有建立连接,此时若连接池中没有空闲的连接,但是又没有达到maxActive并发的最大连接数,则在连接池中建立连接。
3.然后在WEB-INF中新建web.xml文件,然后将下面内容复制,保存
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0"
metadata-complete="true">
<display-name>test</display-name>
<welcome-file-list>
<welcome-file>test.jsp</welcome-file>
</welcome-file-list>
<resource-ref>
<description>DB Connection</description>
一.设计测试用的数据库
1.新建数据库
create database testmysql;
2.新建一个用户信息数据表
create table test(
username varchar(20) primary key,
password varchar(20));
3.给新表插入数据信息
insert into test values('keivn','123456');
二. 设计局部数据源和连接池
1.在webapps目录中新建test目录,然后在test中分别新建WEB-INF和META-INF目录,在WEB-INF目录
中新建classes和lib目录,将mysql数据库驱动文.jar放进lib目录中
这里我使用的版本是mysql-connector-java-5.1.22-bin.jar
2.在META-INF目录中新建context.xml文件,然后将下面内容复制,保存
<?xml version='1.0' encoding='utf-8'?>
<Context>
<Resource name="jdbc/mysql"
auth="Container"
driverClassName="com.mysql.jdbc.Driver"
type="javax.sql.DataSource"
url="jdbc:mysql://localhost:3306/testmysql"
username="root"
password="123456"
maxActive="100"
maxIdle="30"
maxWait="10000" />
</Context>
context.xml中的参数的解析如下:
name属性是数据源名称,通常采取jdbc/**.
type属性是数据源方式。
driverClassName属性是驱动程序名称。
username,password,数据库名称和密码
url:访问的数据库路径。
maxActive属性是并发连接的最大数。设置为0则无限制。
maxWait属性是等待连接的最大连接的时间。
maxIdle属性是连接池中空闲的连接的个数。
上文中的设置的 maxActive="100"说明可以最大连接的个数为100个,再建立连接,则出现异常。
而maxIdle="30"说明当关闭数据库时(不是真正的断开连接,而是归还连接池中)连接池中最大可以有空闲的连接数为30个。
若是再有建立连接,此时若连接池中没有空闲的连接,但是又没有达到maxActive并发的最大连接数,则在连接池中建立连接。
3.然后在WEB-INF中新建web.xml文件,然后将下面内容复制,保存
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0"
metadata-complete="true">
<display-name>test</display-name>
<welcome-file-list>
<welcome-file>test.jsp</welcome-file>
linux内核中的信号机制--信号发送
Kernel version:2.6.14
CPU architecture:ARM920T
Author:ce123(http://blog.csdn.net/ce123)
应用程序发送信号时,主要通过kill进行。注意:不要被“kill”迷惑,它并不是发送SIGKILL信号专用函数。这个函数主要通过系统调用sys_kill()进入内核,它接收两个参数:
第一个参数为目标进程id,kill()可以向进程(或进程组),线程(轻权线程)发送信号,因此pid有以下几种情况:
- pid>0:目标进程(可能是轻权进程)由pid指定。
- pid=0:信号被发送到当前进程组中的每一个进程。
- pid=-1:信号被发送到任何一个进程,init进程(PID=1)和以及当前进程无法发送信号的进程除外。
- pid<-1:信号被发送到目标进程组,其id由参数中的pid的绝对值指定。
由于sys_kill处理的情况比较多,分析起来比较复杂,我们从太累了入手,这个函数把信号发送到由参数指定pid指定的线程(轻权进程)中。tkill的内核入口是sys_tkill(kernel/signal.c),其定义如下:
/* * Send a signal to only one task, even if it's a CLONE_THREAD task. */ asmlinkage long sys_tkill(int pid, int sig) { struct siginfo info; int error; struct task_struct *p; /* This is only valid for single tasks */ if (pid <= 0)//对参数pid进行检查 return -EINVAL; info.si_signo = sig; //根据参数初始化一个siginfo结构 info.si_errno = 0; info.si_code = SI_TKILL; info.si_pid = current->tgid; info.si_uid = current->uid; read_lock(&tasklist_lock); p = find_task_by_pid(pid);//获取由pid指定的线程的task_struct结构 error = -ESRCH; if (p) { error = check_kill_permission(sig, &info, p);//权限检查 /* * The null signal is a permissions and process existence * probe. No signal is actually delivered. */ if (!error && sig && p->sighand) { spin_lock_irq(&p->sighand->siglock); handle_stop_signal(sig, p); //对某些特殊信号进程处理,例如当收到SIGSTOP时,需要把信号队列中的SIGCONT全部删除 error = specific_send_sig_info(sig, &info, p);//把信号加入到信号队列 spin_unlock_irq(&p->sighand->siglock); } } read_unlock(&tasklist_lock); return error; }
sys_tkill函数主要是通过pecific_send_sig_info()函数实现的,下面我们看一下pecific_send_sig_info()(kernel/signal.c)的定义:
static int specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) { int ret = 0; if (!irqs_disabled()) BUG(); assert_spin_locked(&t->sighand->siglock); if (((unsigned long)info > 2) && (info->si_code == SI_TIMER)) /* * Set up a return to indicate that we dropped the signal. */ ret = info->si_sys_private; /*信号被忽略*/ /* Short-circuit ignored signals. */ if (sig_ignored(t, sig)) goto out; /* Support queueing exactly one non-rt signal, so that we can get more detailed information about the cause of the signal. */ if (LEGACY_QUEUE(&t->pending, sig)) goto out; ret = send_signal(sig, info, t, &t->pending);//实际的发送工作 if (!ret && !sigismember(&t->blocked, sig)) signal_wake_up(t, sig == SIGKILL); out: return ret; }首先调用sig_ignored检查信号是否被忽略,然后检查发送的信号是不是普通信号,如果是普通信号,就需要根据信号位图来检查当前信号队列中是否已经存在该信号,如果已经存在,对于普通信号不需要做任何处理。然后调用send_signal来完成实际的发送工作,send_signal()是信号发送的重点,除sys_tkill之外的函数,最终都是通过send_signal()来完成信号的发送工作的。
这里注意到想send_signal()传递的参数时t->pending,也就是连接Private Signal Queue的那条链。最后,如果发送成功就调用signal_wake_up()来唤醒目标进程,这样可以保证该进程进入就绪状态,从而有机会被调度执行信号处理函数。
现在我们来看看send_signal()(kernel/signal.c)函数,这个函数的主要工作就是分配并初始化一个sigqueue结构,然后把它添加到信号队列中。
static int send_signal(int sig, struct siginfo *info, struct task_struct *t, struct sigpending *signals) { struct sigqueue * q = NULL; int ret = 0; /* * fast-pathed signals for kernel-internal things like SIGSTOP * or SIGKILL. */ if ((unsigned long)info == 2) goto out_set; /* Real-time signals must be queued if sent by sigqueue, or some other real-time mechanism. It is implementation defined whether kill() does so. We attempt to do so, on the principle of least surprise, but since kill is not allowed to fail with EAGAIN when low on memory we just make sure at least one signal gets delivered and don't pass on the info struct. */ q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN && ((unsigned long) info < 2 || info->si_code >= 0)));//分配sigqueue结构 if (q) {//如果成功分配到sigqueue结构,就把它添加到队列中,并对其初始化 list_add_tail(&q->list, &signals->list); switch ((unsigned long) info) { case 0: q->info.si_signo = sig; q->info.si_errno = 0; q->info.si_code = SI_USER; q->info.si_pid = current->pid; q->info.si_uid = current->uid; break; case 1: q->info.si_signo = sig; q->info.si_errno = 0; q->info.si_code = SI_KERNEL; q->info.si_pid = 0; q->info.si_uid = 0; break; default: copy_siginfo(&q->info, info);//拷贝sigqueue结构 break; } } else { if (sig >= SIGRTMIN && info && (unsigned long)info != 1 && info->si_code != SI_USER) /* * Queue overflow, abort. We may abort if the signal was rt * and sent by user using something other than kill(). */ return -EAGAIN; if (((unsigned long)info > 1) && (info->si_code == SI_TIMER)) /* * Set up a return to indicate that we dropped * the signal. */ ret = info->si_sys_private; } out_set: sigaddset(&signals->signal, sig);//设置信号位图 return ret; }从上面的分析可以看出,我们看到信号被添加到信号队列之后,会调用signal_wake_up()唤醒这个进程,signal_wake_up()(kernel/signal.c)的定义如下:
/* * Tell a process that it has a new active signal.. * * NOTE! we rely on the previous spin_lock to * lock interrupts for us! We can only be called with * "siglock" held, and the local interrupt must * have been disabled when that got acquired! * * No need to set need_resched since signal event passing * goes through ->blocked */ void signal_wake_up(struct task_struct *t, int resume) { unsigned int mask; set_tsk_thread_flag(t, TIF_SIGPENDING);//为进程设置TIF_SIGPENDING标志 /* * For SIGKILL, we want to wake it up in the stopped/traced case. * We don't check t->state here because there is a race with it * executing another processor and