1. 程式人生 > >linux內核 信號

linux內核 信號

types.h 好的 獲取 並且 reg blog 請求 ons ase

簡單的寫一個小程序了解一些信號的機理

盡管阻塞和非阻塞操作和 select 方法的結合對於查詢設備在大部分時間是足
夠的, 一些情況還不能被我們迄今所見到的技術來有效地解決.
讓我們想象一個進程, 在低優先級上執行一個長計算循環, 但是需要盡可能快
的處理輸入數據. 如果這個進程在響應新的來自某些數據獲取外設的報告, 它
應當立刻知道當新數據可用時. 這個應用程序可能被編寫來調用 poll 有規律
地檢查數據, 但是, 對許多情況, 有更好的方法. 通過使能異步通知, 這個應
用程序可能接受一個信號無論何時數據可用並且不需要讓自己去查詢.
用戶程序必須執行 2 個步驟來使能來自輸入文件的異步通知. 首先, 它們指定
一個進程作為文件的擁有者. 當一個進程使用 fcntl 系統調用發出 F_SETOWN
命令, 這個擁有者進程的 ID 被保存在 filp->f_owner 給以後使用. 這一步對
內核知道通知誰是必要的. 為了真正使能異步通知, 用戶程序必須設置 FASYNC
標誌在設備中, 通過 F_SETFL fcntl 命令.
在這 2 個調用已被執行後, 輸入文件可請求遞交一個 SIGIO 信號, 無論何時
新數據到達. 信號被發送給存儲於 filp->f_owner 中的進程(或者進程組, 如
果值為負值).
例如, 下面的用戶程序中的代碼行使能了異步的通知到當前進程, 給 stdin 輸
入文件:
signal(SIGIO, &input_handler); /* dummy sample; sigaction() is better */
fcntl(STDIN_FILENO, F_SETOWN, getpid());
oflags = fcntl(STDIN_FILENO, F_GETFL);
fcntl(STDIN_FILENO, F_SETFL, oflags | FASYNC);
這個在源碼中名為 asynctest 的程序是一個簡單的程序, 讀取 stdin. 它可用
來測試 scullpipe 的異步能力. 這個程序和 cat 類似但是不結束於文件尾;
它只響應輸入, 而不是沒有輸入.
註意, 但是, 不是所有的設備都支持異步通知, 並且你可選擇不提供它. 應用
程序常常假定異步能力只對 socket 和 tty 可用.
輸入通知有一個剩下的問題. 當一個進程收到一個 SIGIO, 它不知道哪個輸入
文件有新數據提供. 如果多於一個文件被使能異步地通知掛起輸入的進程, 應
用程序必須仍然靠 poll 或者 select 來找出發生了什麽.

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <asm-generic/ioctl.h>
#include <asm/uaccess.h>
#include <linux/wait.h>
#include 
<linux/sched.h> #include <asm/atomic.h> #include <linux/semaphore.h> #define MAGIC ‘B‘ #define GET_BTN_VAL _IOR(MAGIC, 1, unsigned long) typedef struct { unsigned int gpio; unsigned int btn; unsigned int irq; char* name; }irq_typedef;
static irq_typedef irqsource[] = { {EXYNOS4_GPX3(2),1,0,"btn1"}, {EXYNOS4_GPX3(3),2,0,"btn2"}, {EXYNOS4_GPX3(4),3,0,"btn3"}, {EXYNOS4_GPX3(5),4,0,"btn4"} }; DEFINE_SEMAPHORE(btn_sem); DECLARE_WAIT_QUEUE_HEAD(btn_wait_que); static int condition; static unsigned long btn_num; static irqreturn_t gpio_irq_handler(int irq, void *dev) { irq_typedef* curdev = (irq_typedef *)dev; printk("%s\n",curdev->name); printk("btn(drv):%d\n",curdev->btn); btn_num = curdev->btn; condition=1; wake_up(&btn_wait_que); return 0; } static int btn_open(struct inode *inod, struct file *fil) { if(!down_interruptible(&btn_sem)) { up(&btn_sem); return -EINTR; } return 0; } static int btn_release(struct inode *inod, struct file *fil) { up(&btn_sem); return 0; } static long btn_ioctl(struct file *fil, unsigned int cmd, unsigned long arg) { unsigned long ret; void __user *argp = (void __user *)arg; wait_event_interruptible(btn_wait_que, condition); condition = 0; switch(cmd) { case GET_BTN_VAL: ret = copy_to_user((void __user *) argp, (void *)&btn_num,4); // put_user(btn_num, (unsigned int __user *) argp); break; default:return -EINVAL; } return ret; } static struct file_operations btn_irq_fops = { .owner = THIS_MODULE, .open = btn_open, .release = btn_release, .unlocked_ioctl = btn_ioctl, }; static struct miscdevice btn_irq_misc = { .minor = 255, .name = "btn", .fops = &btn_irq_fops, }; static __init int btn_irq_init(void) { int i,ret; misc_register(&btn_irq_misc); for(i=0;i<4;i++) { irqsource[i].irq = gpio_to_irq(irqsource[i].gpio); ret = request_irq(irqsource[i].irq,gpio_irq_handler,IRQF_TRIGGER_FALLING,irqsource[i].name, &irqsource[i]); } return ret; } static __exit void btn_irq_exit(void) { int i; for(i=0;i<4;i++) free_irq(irqsource[i].irq, &irqsource[i]); misc_deregister(&btn_irq_misc); } module_init(btn_irq_init); module_exit(btn_irq_exit); MODULE_LICENSE("GPL");
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>

#define     MAGIC                     ‘B‘
#define     GET_BTN_VAL              _IOR(MAGIC, 1, unsigned long)

int main(int argc,char *argv[])
{
    int btn_fd,btn_val=0;

    if(argc!=2)
    {
        printf("Usage:<%s> </dev/?node>\n",argv[0]);
        return -1;
    }

    btn_fd = open(argv[1],O_RDONLY);    
    
    if(btn_fd<0)    
        return -1;

    while(1)
    {
        // ioctl(btn_fd,GET_BTN_VAL,btn_val);
        ioctl(btn_fd,GET_BTN_VAL,&btn_val);
        // sleep(1);

        printf("btn_val(irq):%d\n",btn_val);
    }
}

obj-m    += btnirq.o
SOURCE =btntest.o

CROSS_COMPLIE = arm-linux-
CC = $(CROSS_COMPLIE)gcc

KERNDIR = /file/samsung/linux-3.5
#CURDIR  = $(shell pwd)
CURDIR  = `pwd`

.PHONY: module clean

all: module $(SOURCE:.o=)

module:
    $(MAKE) -C $(KERNDIR) M=$(CURDIR) modules

$(SOURCE:.o=):$(SOURCE)
    $(CC) -o $@ $^

%.o:%.c
    $(CC) -c $<

clean:
    $(MAKE) -C $(KERNDIR) M=$(CURDIR) clean
    rm $(SOURCE:.o=)

linux內核 信號