첫째, 인터럽트 동작
리눅스 커널은 컴퓨터에 연결된 모든 하드웨어 장치를 관리 할 필요가있다. 당신은 무엇보다도 이러한 장치를 관리 할, 그들은 작업에 서로 통신합니다.
일반적으로이 기능을 달성하기 위해 두 가지 옵션이 있습니다 :
- 정기적으로 장치의 상태를 조회하고 적절한 치료를 만들기 위해 설문 조사 (폴링) 커널;
- 인터럽트 커널 하드웨어 신호는 (커널은 하드웨어 활성 구상된다)이 필요하므로 (인터럽트).
더 많은 CPU 시간과 낮은 효율을 차지하게됩니다 폴링 방법을 사용합니다. 예를 들어 프로세스가 키를 누르면되지 않은 쿼리를 계속 할 필요가, 버튼을 누르지있을 때 읽을 수 있습니다. 이 작업은 CPU 시간을 많이했다 그래서, CPU 낭비 많은 노력을합니다. 을 사용하면 이런 메커니즘을 제공 중단. 버튼이 눌러지지 않은 경우, 현재의 프로세스는 다른 프로세스로 제어를 중단. 운영 체제가 프로세스를 계속 할 수 있도록, 현재의 프로세스 활동로 설정되어있을 때 버튼을 누르면됩니다.
두 인터럽트 관리를 리눅스
리눅스 커널의 인터럽트 번호 모두 균일하는 이용
irq_desc
구조 배열 중단 설명. (인터럽트 번호를 공유하거나 인터럽트의 세트) 배열 엔트리는 인터럽트를 사용한다.
struct irq_desc
레코드 구조, 인터럽트는 인터럽트 상태의 이름은, 하부 하드웨어 인터페이스 (인터럽트 삭제 가능 인터럽트 마스크 가능 인터럽트) 입구의 인터럽트 핸들러에 액세스하는
사용자는 인터럽트 핸들러의 등록을 호출 할 수있는이.
1 구조체 irq_desc
struct irq_desc
에서include\linux\irq.h
정의 파일의 내부
struct irq_desc {
irq_flow_handler_t handle_irq; /* 当前中断的处理函数入口 */
struct irq_chip *chip; /* 底层硬件访问 */
...
struct irqaction *action; /* 用户注册的中断处理函数链表 */
unsigned int status; /* IRQ状态 */
...
const char *name; /* 中断函数名 */
} ____cacheline_internodealigned_in_smp;
에이. handle_irq
handle_irq
이 아니면 인터럽트 핸들러 입구의 그룹입니다. 인터럽트가 발생하면, 그것은 호출asm_do_IRQ
기능을. 인터럽트 번호 안쪽이 대응 함수 호출irq_desc
어레이 제품handle_irq
.
에서handle_irq
내부 사용chip
실드를 활성화하는 인터페이스 멤버, 인터럽트를 취소합니다. 일레븐에 등록 된 사용자 호출action
핸들러 내부의 목록을.
비. 구조체 irq_chip
에 irq_chip 구조체
include\linux\irq.h
정의 파일의 내부
struct irq_chip {
const char *name;
/* 启动中断,如果不设置则缺省为 "enable" */
unsigned int (*startup)(unsigned int irq);
/* 关闭中断,如果不设置则缺省为 "disable" */
void (*shutdown)(unsigned int irq);
/* 使能中断,如果不设置则缺省为"unmask" */
void (*enable)(unsigned int irq);
/* 禁止中断,如果不设置则缺省为"mask" */
void (*disable)(unsigned int irq);
/* 响应中断,一般是清除当前的中断,使得可以接收下一个中断 */
void (*ack)(unsigned int irq);
/* 屏蔽中断源 */
void (*mask)(unsigned int irq);
/* 屏蔽和响应中断 */
void (*mask_ack)(unsigned int irq);
/* 开启中断 */
void (*unmask)(unsigned int irq);
....
};
씨. 구조체 irqaction
struct irqaction
구조에서include\linux\interrupt.h
정의 파일의 내부.
사용자에게 등록 된 인터럽트 핸들러 각irqaction
인터럽트 (예를 들어 공유 인터럽트)를 설명하기위한 구조는 복수의 핸들러가있다.
그들의irqaction
구조action
체인 헤더의 연결리스트로
struct irqaction {
/* 用户注册的中断处理函数 */
irq_handler_t handler;
/* 中断的标志,是否是共享中断,中断的触发方式是电平触发,还是边沿触发 */
unsigned long flags;
cpumask_t mask;
/* 用户注册时,给的中断的名字 */
const char *name;
/* handler 中断函数的参数,也可以用来区分共享中断 */
void *dev_id;
/* 链表的指针 */
struct irqaction *next;
/* 中断号 */
int irq;
struct proc_dir_entry *dir;
};
2. 요약
용
struct irq_desc
어레이struct irq_chip
구조와struct irqaction
다음과 같이 세 가지의 관계 :
셋째, 인터럽트 핸들러 초기화
1 인터럽트 핸들러 초기화
에서
init\Main.c
문서start_kernel
하는 기능을 호출init_IRQ()
이 인터럽트 초기화 아키텍처입니다 기능
2 init_IRQ 함수
init_IRQ
그것은 인터럽트 처리 아키텍처를 초기화하는 데 사용의arch\arm\kernel\irq.c
파일 내부
void __init init_IRQ(void)
{
int irq;
/* 初始化irq_desc[] 每一项的中断状态 */
for (irq = 0; irq < NR_IRQS; irq++)
irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE;
...
/* 架构相关的中断初始化函数 */
init_arch_irq();
}
3 init_arch_irq
init_arch_irq
함수 포인터이며,arch\arm\kernel\setup.c
파일setup_arch()
기능이 초기화됩니다
void __init setup_arch(char **cmdline_p)
{
...
init_arch_irq = mdesc->init_irq;
...
}
mdesc->init_irq
받는 포인트arch\arm\plat-s3c24xx\irq.c
파일s3c24xx_init_irq()
기능을합니다.
MACHINE_START(S3C2440, "SMDK2440")
매크로는 정의하는 데 사용되는struct machine_desc
구조
의 구조arch\arm\mach-s3c2440\Mach-smdk2440.c
정의 파일을 내부 초기화init_irq
가리키는s3c24xx_init_irq()
함수
MACHINE_START(S3C2440, "SMDK2440")
/* Maintainer: Ben Dooks <[email protected]> */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
/* init_irq成员在这里初始化 */
.init_irq = s3c24xx_init_irq,
.map_io = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END
4 s3c24xx_init_irq 함수
s3c24xx_init_irq()
기능arch\arm\plat-s3c24xx\irq.c
모든 관련 데이터 구조를 조작 그의 칩 (코드의 코드 블록의 일부로서) 정의 (irq_desc [IRQ] .chip) ,, 및 초기화 처리기 입력 (irq_desc [IRQ] .handle_irq).
에서IRQ_EINT0
그리고IRQ_EINT3
예를 들어,set_irq_chip
것이다 함수irq_desc[irqno].chip = &s3c_irq_eint0t4
는 수 후irq_desc[irqno].chip
인터럽트를 가능 터치 방식 함수 포인터 구조를 제공 인터럽트 마스크
set_irq_handler
기능이 인터럽트 핸들러의 엔트리에 제공된다irq_desc[irqno].handle_irq = handle_edge_irq
발생한 인터럽트handle_edge_irq
는 핸들러 등록 된 사용자 특정 호출
irq_desc[irqno].falgs
설정 이다IRQF_VALID
void __init s3c24xx_init_irq(void)
{
...
/* external interrupts */
for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
irqdbf("registering irq %d (ext int)\n", irqno);
set_irq_chip(irqno, &s3c_irq_eint0t4);
set_irq_handler(irqno, handle_edge_irq);
set_irq_flags(irqno, IRQF_VALID);
}
for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
irqdbf("registering irq %d (extended s3c irq)\n", irqno);
set_irq_chip(irqno, &s3c_irqext_chip);
set_irq_handler(irqno, handle_edge_irq);
set_irq_flags(irqno, IRQF_VALID);
}
...
}
5 set_irq_chip 함수
int set_irq_chip(unsigned int irq, struct irq_chip *chip)
{
struct irq_desc *desc;
unsigned long flags;
/* 判断是否超过最大的中断号 */
if (irq >= NR_IRQS) {
printk(KERN_ERR "Trying to install chip for IRQ%d\n", irq);
WARN_ON(1);
return -EINVAL;
}
if (!chip)
chip = &no_irq_chip;
/* 通过中断号找到irq_desc数组对应的数组项 */
desc = irq_desc + irq;
spin_lock_irqsave(&desc->lock, flags);
/* 判断 chip 的成员即&s3c_irq_eint0t4的成员是否为空,如果为空就设置为默认的操作函数 */
irq_chip_set_defaults(chip);
/* 设置irq_desc[].chip成员 */
desc->chip = chip;
spin_unlock_irqrestore(&desc->lock, flags);
return 0;
5 set_irq_handler 함수
set_irq_handler(unsigned int irq, irq_flow_handler_t handle)
{
__set_irq_handler(irq, handle, 0, NULL);
}
/***************************************************************************************/
__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
const char *name)
{
struct irq_desc *desc;
unsigned long flags;
/* 通过中断号找到irq_desc数组对应的数组项 */
desc = irq_desc + irq;
...
/* 中间还会做一些判断 */
...
/* 设置中断处理函数,名字*/
desc->handle_irq = handle;
desc->name = name;
/* 设置中断的状态,开启中断 */
if (handle != handle_bad_irq && is_chained) {
desc->status &= ~IRQ_DISABLED;
desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
desc->depth = 0;
desc->chip->unmask(irq);
}
}
도 6은 작동 set_irq_flags
void set_irq_flags(unsigned int irq, unsigned int iflags)
{
struct irq_desc *desc;
unsigned long flags;
if (irq >= NR_IRQS) {
printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq);
return;
}
/* 找到数组项 */
desc = irq_desc + irq;
spin_lock_irqsave(&desc->lock, flags);
/* 设置中断状态 */
desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
if (iflags & IRQF_VALID)
desc->status &= ~IRQ_NOREQUEST;
if (iflags & IRQF_PROBE)
desc->status &= ~IRQ_NOPROBE;
if (!(iflags & IRQF_NOAUTOEN))
desc->status &= ~IRQ_NOAUTOEN;
spin_unlock_irqrestore(&desc->lock, flags);
}
IV 요약
대해 사실 아키텍처 인터럽트 처리 초기화 처리
irq_desc[]
어레이의 초기화 각각 초기화된다.
브레이크 인터럽트에 의해 또는 일련의irq_desc[]
항목 배열하여 관리한다.
내부 항목 배열handle_irq
chip
action
세 가지 중요한 구조 부재.
- handle_irq 현재 인터럽트 핸들러
- 칩 연관된 기본 하드웨어 처리기 (트리거 인터럽트 모드, 마스크 가능한 인터럽트의 인터럽트 활성화)
- 액션리스트 헤드리스트에 연결된 사용자 등록 처리 기능은, 인터럽트가 발생하면, 등록 된 사용자는 인터럽트 서비스 함수 내부에서 오는 호출