package com.clark;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class UserBean implements InitializingBean, DisposableBean {
private String username;
private int age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void init() {
this.username = "zhangsan";
this.age = 20;
}
public void clear() {
this.username = "";
this.age = 0;
}
//销毁
public void destroy() throws Exception {
this.username = "";
this.age = 0;
}
//在调用properties文件后初始化设值
public void afterPropertiesSet() throws Exception {
this.username = "wangwu";
this.age = 20;
}
}
package com.clark;
import java.util.Date;
import java.util.Locale;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
//测试类
public class Test {
public static void main(String[] args) {
ApplicationContext context=new FileSystemXmlApplicationContext("src/applicationContext.xml");
UserBean userBean=(UserBean)context.getBean("user");
System.out.println("username="+userBean.getUsername());
System.out.println("age="+userBean.getAge());
//之所以使用Object[]数组,是因为其资源配置文件.properties中对应的参数有两个
Object[] objs=new Object[]{userBean.getUsername(),new Date().toString()};
//获取资源文件,Locale.CHINA指定采用何种语言
String str=context.getMessage("www.clark.com", objs, Locale.CHINA);
System.out.println(str);
}
}
资源文件是:message_en_US.properties下为:
www.clark.com=welcome {0},now time is\:{1}
message_zh_CN.properties中为:(最原始为www.clark.com=欢迎 {0},现在时间是:{1})------这就是编译器的强大所在
www.clark.com=\u6B22\u8FCE {0},\u73B0\u5728\u65F6\u95F4\u662F\:{1}
applicationContext.xml文件为
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="user" class="com.clark.UserBean"
abstract="false" singleton="true"
lazy-init="default" autowire="default"
dependency-check="default" destroy-method="clear">
</bean>
<!-- 配置国际化 配置messageSource这个bean(注意:一定是messageSource
而不是messageResource ,这是Spring规定的),而且资源配置*_en_US.properties等文件必须位于src目录下
否则,加载的时候找不到,会报错
-->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"
abstract="false" singleton="true" lazy-init="default"
autowire="default" dependency-check="default">
<!-- 国际化资源文件.properties中对应的key名称 -->
<property name="basenames">
<list>
<!-- 此值对应资源文件的名称message_en_US中的message必须与其对应 -->
<value>message</value>
</list>
</property>
</bean>
</beans>
1.进程控制块(PCB)
进程控制块包含进程的描述信息、控制信息以及资源信息。进程在创建时应该首先创建其PCB,当进程完成后,系统则释放PCB,进程随之消亡。
进程控制块包含如下几个部分:标识符信息、处理机状态信息、进程调度信息和进程控制信息。通过对PCB的操作,系统为有关进程分配资源从而使有关进程得以被调度自行,执行结束后,通过释放PCB来释放进程所占用的资源。
2.进程状态及状态转换
尽管每个进程是个独立的实体,具有自己的程序计数器、运行空间等。但由于程序或进程之间可能由于等等I/O操作、竞争资源以及相互协作等原因产生了走走停停的动态性。因此,一个进程在生存周期内,可有多种状态。进程在生存周期内至少有三种基本状态:
(1)运行状态:当进程已获得处理机,其程序正在处理机上执行,此时的进程状态称为执行状态。
(2)就绪状态:当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态。根据PCB的形式将其排成一个或多个就绪队列。
(3)阻塞状态:阻塞状态也称等待/封锁/睡眠状态(等待的事件发生唤醒它就ok了)。正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。引起进程阻塞的事件可有多种,例如,等待I/O完成、申请缓冲区不能满足、等待信件(信号)等。同样根据PCB的形式嘴直一个或多个阻塞队列。
一个操作系统设计多少状态与系统对进程的管理方式有关,也与系统的资源有关。
进程在生存周期内可以由一个状态转换到另一个状态,具体如下:
(1)就绪→执行:选择一个就绪队列的进程,分派处理机给它,该进程便由就绪状态转变成执行状态。(具体怎么选择进程由调度策略决定)
(2)运行→就绪:处于执行状态的进程在其执行过程中,因分配给它的一个时间片已用完而不得不让出处理机,于是进程从执行状态转变成就绪状态。
(3)运行→阻塞:正在执行的进程因等待某种事件发生而无法继续执行时,或因为某些条件无法得到满足,便从执行状态变成阻塞状态。
(4)阻塞→就绪:处于阻塞状态的进程,若其等待的事件已经发生,于是进程由阻塞状态转变为就绪状态。
3.挂起状态的引入
由于处理器的速率要远远高于I/O的速率,致使所有进程都已计算完,都在等待I/O而处于阻塞状态,这时没就绪队列中没有运行的作业,从而CPU空闲下来。但在后备作业上(外存)希望“计算”的进程由于系统此时无法容纳新的作业而无法进入内存运行。解决这个问题的办法有两种:
(1)扩内存:不太现实。
(2)软件方法:将一些处于阻塞状态的进程将其部分或全部转移到交换区(磁盘辅助空间),这种情况下引入暂时挂起状态——使一些进程已占用的系统资源让出部分或全部,以供其他进程利用。
这种情况下,进程状态转移如下图:
(1)活动阻塞→静止阻塞:当前系统中没有就绪态进程,就将处于阻塞态的进程至少挂起一个,从而进入静止阻塞状态,为没有被阻塞的进程让出主存空间。
(2)静止阻塞→静止就绪:等待事件发生了,则将静止阻塞状态改为静止就绪。
(3)静止就绪→活动就绪:主存中没有就绪进程,操作系统需要调入一个进程。还有一种情况静止就绪的进程优先级高于就绪状态的优先级时,操作系统往往将处于静止就绪的进程激活为就绪状态。
(4)活动就绪→静止就绪:通常操作系统更倾向于将活动阻塞状态挂起为静止阻塞。因为就绪态进程属于可运行状态,而阻塞态进程占据着主存空间又处于暂时“无法运行”状态。有一种情况是处于高优先级的阻塞进程能很快进入就绪状态,则可能会挂起低优先级的就绪进程而不是高优先级的阻塞进程。
(5)静止阻塞→活动阻塞:比较少见。因为一个进程处于阻塞状态,且不在内存中,调它如内存意义不大。有种情况时静止阻塞中存在一个进程的优先级比静止就绪队列任何一个进程优先级都高,且操作系统确定等待的事很快会发生。
(6)运行→静止就绪:如果在静止阻塞队列中有优先级更高而不会再被阻塞,则操作系统会立刻抢占这个进程,将当前运行的进程转到静止就绪。
引起挂起的主要原因式提供更多的主存空间,以调入可运行的进程或为其他进程分配更多的空间。
注:挂起与激活一对,阻塞与唤醒
引言 中断(异常)系统,可以说是计算机体系结构重要的组成部分,也是最复杂的部分。
现在的很多外设,都提供中断处理机制,来减少CPU的一直占用时间。
本小节就通过一个简单的例子,来说明openrisc的中断机制的使用方法。
1,功能简介 本小节实现一个wishbone slave模块(mycore),此模块接收其对应的linux driver的指令,产生中断信号。
linux driver注册中断处理程序,记录中断发生的次数。
本实验中,在模块加载时(insmod ip_mkg.ko)时触发一次中断。在测试程序read时触发一次中断。
通过代码内部打印查看结果,通过cat /proc/stat查看结果。
2,OR中断资源分析 2.1 硬件部分
1,通过下面的代码可以看出:
OR最多支持的外部中断线的数目为:31.其中只有(2~31)可以使用。
2,通过下面的代码可以看出:
目前已经使用的中断线为:2~23。
3,通过下面的综合结果可以看出:
真正使用的为:2,4,6,14,15,16,20,21.共8根。具体如下:SDC:3根。
USB:2根。
UART:1根。
simple_spi:1根。
eth:1根。
2.2 软件部分 通过下面的linux kernel代码可以看出:
OR的中断线有32根。(与硬件不匹配)。
2.3 本实验使用的中断线为:24。
3,实验内容 3.1 RTL编码 1>mycore.v
/* * * rill create 2013-05-07 * */ `include "orpsoc-defines.v" module mycore ( intr_o,//interrupt output wb_clk, wb_rst, wb_dat_i, wb_adr_i, wb_sel_i, wb_cti_i, wb_bte_i, wb_we_i, wb_cyc_i, wb_stb_i, wb_dat_o, wb_ack_o, wb_err_o, wb_rty_o ); output reg intr_o; input [addr_width-1:0] wb_adr_i; input wb_stb_i; input wb_cyc_i; input [2:0] wb_cti_i; input [1:0] wb_bte_i; input wb_clk; input wb_rst; input [31:0] wb_dat_i; input [3:0] wb_sel_i; input wb_we_i; output reg [31:0] wb_dat_o; output reg wb_ack_o; output wb_err_o; output wb_rty_o; //external parameters parameter addr_width = 32; parameter mycore_adr = 0; //local regs reg [addr_width-1:0] num_1; reg [addr_width-1:0] num_2; reg [addr_width-1:0] sum; parameter s_idle = 3'b000; parameter s_read = 3'b001; parameter s_write = 3'b010; reg [2:0] state = s_idle; //irq status parameter irq_idle = 3'b000; parameter irq_action = 3'b001; reg [2:0] irq_state = irq_idle; reg [7:0] irq_done;//irq flag assign wb_err_o=0; assign wb_rty_o=0; always @(*)//sum process begin sum = num_1 + num_2; end always @(posedge wb_clk)//interrupt process begin if(wb_rst) begin intr_o <= 1'b0; end else begin case (irq_state) irq_idle: begin intr_o <= 1'b0; if( (32'd1 == num_1) && (irq_done == 8'd0) ) begin irq_state <= irq_action; irq_done <= 8'd1; end else if( (32'd2 == num_1) && (irq_done == 8'd1) ) begin irq_state <= irq_action; irq_done <= 8'd2; end else if( (32'd3 == num_1) && (irq_done == 8'd2) ) begin irq_state <= irq_action; irq_done <= 8'd3; end else if( (32'd4 == num_1) && (irq_done == 8'd3) ) begin irq_state <= irq_action; irq_done <= 8'd4; end else begin irq_state <= irq_idle; end end irq_action: begin intr_o <= 1'b1; irq_state <= irq_idle; end default: begin irq_state <= irq_idle; intr_o <= 1'b0; end endcase end end always @(posedge wb_clk)//wishbone interface begin if(wb_rst) begin state <= s_idle; end else begin case(state) s_idle: begin wb_dat_o <= 1'b0; wb_ack_o <= 1'b0; if(wb_stb_i && wb_cyc_i && wb_we_i) begin state <= s_write; end else if(wb_stb_i && wb_cyc_i && !wb_we_i) begin state <= s_read; end else begin state <= s_idle; end end s_write: begin if(wb_adr_i == {mycore_adr,24'h000000}) begin num_1 <= wb_dat_i; wb_ack_o <= 1'b1; end else if(wb_adr_i == {mycore_adr,24'h000004}) begin num_2 <= wb_dat_i; wb_ack_o <= 1'b1; end else begin //wb_ack_o=1'b0; end state <= s_idle; end s_read: begin if(wb_adr_i=={mycore_adr,24'h000000}) begin wb_dat_o <= num_1; wb_ack_o <= 1'b1; end else if(wb_adr_i=={mycore_adr,24'h000004}) begin wb_dat_o <= num_2; wb_ack_o <= 1'b1; end else if(wb_adr_i=={mycore_adr,24'h000008}) begin wb_dat_o <= sum; wb_ack_o <= 1'b1; end else begin wb_dat_o=0; wb_ack_o <= 1'b1; end state <= s_idle; end default: begin state <= s_idle; end endcase end end endmodule /************** EOF ****************/
2>例化:orpsoc_top.v
3.2 RTL综合 如下图,中断线多了一根:共9根。
3.3 linux driver编码 1>ip_mkg.c
/* * * rill mkg driver * */ #include <linux/vmalloc.h> #include <linux/slab.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/fs.h> #include <asm/uaccess.h> /* get_user and put_user */ //#include <linux/clk.h> //#include <linux/ioport.h> #include <asm/io.h> /*ioremap*/ #include <linux/platform_device.h> /*cleanup_module*/ #include <asm-generic/io.h> #include "ip_mkg.h" #include <linux/interrupt.h> volatile int g_irq_test_counter = 0; void __iomem *g_mkg_mem_base = NULL; static int device_open(struct inode *inode, struct file *file) { g_mkg_mem_base = ioremap(MKG_MEM_BASE,MKG_MEM_LEN); if(NULL == g_mkg_mem_base) { printk(KERN_ERR "mkg open ioremap error!\n"); return -1; } else { printk("kernel:mkg open ok!\n"); } return 0; } static int device_release(struct inode *inode, struct file *file) { return 0; } static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t *offset) { /*int ret_val = 0; char * data = NULL; data = (char*)kmalloc(4, GFP_KERNEL); if((ret_val = copy_from_user(new_regs, (struct reg_data*)ioctl_param, sizeof(struct reg_data))) != 0) ioread32(g_mkg_mem_base+length); printk("============read:%d\n",);*/ iowrite32(0x02000000,g_mkg_mem_base); printk("request_irq ==2==!\n"); printk("mkg g_irq_test_counter:%d!\n",(int)g_irq_test_counter); printk("kernel:mkg g_irq_test_counter:%d!\n",(int)g_irq_test_counter); return 1; } static ssize_t device_write(struct file *filp, const char *buffer, size_t count, loff_t *offset) { //iowrite32(2,g_mkg_mem_base); return 1; } long device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { #if 0 int ret_val = 0; unsigned int ret = 0; struct reg_data *new_regs; printk("ioctl======\n"); switch(ioctl_num) { case IOCTL_REG_SET: { new_regs = (struct reg_data*)kmalloc(sizeof(struct reg_data), GFP_KERNEL); if((ret_val = copy_from_user(new_regs, (struct reg_data*)ioctl_param, sizeof(struct reg_data))) != 0) { kfree(new_regs); printk(KERN_ERR " error copy line_datafrom user.\n"); return -1; } //iowrite16(new_regs->value,g_mkg_mem_base+new_regs->addr); kfree(new_regs); } break; case IOCTL_REG_GET: { new_regs = (struct reg_data*)kmalloc(sizeof(struct reg_data), GFP_KERNEL); if((ret_val = copy_from_user(new_regs, (struct reg_data*)ioctl_param, sizeof(struct reg_data))) != 0) { kfree(new_regs); printk(KERN_ERR " error copy line_datafrom user.\n&q