[태그:] softirq

  • linux driver, softIrq 실습

    linux driver, softIrq 실습

    인터럽트 후반부를 처리하는 soft irq를 배웠다. 자 이제 사용해 보자. 불행히도 요즘은 일반화된 tasklet을 사용하고 low level인 soft irq를 사용하지 않는다고 한다. 그래도 아래 사이트에서 강제로?? 사용할 수 있는 방법을 찾았다. 실습하고 쓰지 말아야 한다. 드라이버를 로딩 후 언로딩하면 시스템이 죽어버린다.

    https://embetronicx.com/tutorials/linux/device-drivers/softirq-in-linux-kernel/

    요점은 kernel에서 export_symbol로 raise_softirq, open_softiq 등 3개 함수를 내보내 사용할 수 있게한다. interrrupt.h에 사용자 정의 softirq를 설정해야 한다. 기존 등록된 이벤를 사용하면 시스템이 죽는다.

    https://stackoverflow.com/questions/39691131/undefined-functions-while-compiling-linux-kernel-module

    튜토리얼이 시스템에 장치를 설치하여 인터럽트를 하는 방법으로 했다. 딱히 장치를 추가할 이유가 없는데 왜 했는지 모르겠으나, 아래 사이트에서 간략한 규칙을 찾았다.

    https://temp123.tistory.com/16?category=877924

    https://hyeyoo.com/85

    인터럽트를 만들어야 확인할 수 있다. 리눅스가 제공하는 명령어로 gpio를 쉽게 컨트롤 할 수 있다. 당연하게도 출력으로 설정하고 값을 써야한다.

    https://infoarts.tistory.com/21

    돌고 돌아 장치를 추가하고, 인터럽트를 만들어 softirq를 실행했다. tutorial site에 잘 설명되어 있다. 나중에 디바이스 read, write를 인터럽트로 설정할 수도 있을 듯 하다.

    i@raspberrypi:~/RaspberryDebug/my_driver $ cat Makefile
    obj-m := my_driver.o
    #obj-m := sample_driver.o
    all:
    	make -C /lib/modules/`uname -r`/build M=`pwd` modules
    clean:
    	rm *.o *.ko *.mod  *.mod.c *.mod.o
    
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/irq.h>
    #include <linux/interrupt.h>
    #include <linux/gpio.h>     //GPIO
    
    #include <linux/fs.h>
    #include <linux/cdev.h>
    #include <linux/device.h>
    
    #define GPIO_10_OUT (10)
    unsigned int GPIO_irqNumber;
    
    //softirq handler
    static void pesudo_interrupt_softirq_handler(struct softirq_action *action)
    {
    	pr_info("pesudo interreupt occured\n");
    }
    
    
    static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
    {
    	/* Raise the softirq */
    	raise_softirq(TEST_SOFT_IRQ);
    	return IRQ_HANDLED;
    
    }
    
    
    //device driver \uc791\uc131 \ubd80\ubd84.
    /*************\ub4dc\ub77c\uc774\ubc84 \ud568\uc218 ******************/
    static int mydriver_open(struct inode *inode, struct file *file);
    static int mydriver_release(struct inode *inode, struct file *file);
    static ssize_t mydriver_read(struct file *flip,
    		char *buf, size_t len, loff_t *off);
    static ssize_t mydriver_write(struct file *flip,
    		const char *buf, size_t len, loff_t *off);
    /********************************************/
    
    
    //file operation structure
    
    static struct file_operations fops = 
    {
    	.owner = THIS_MODULE,
    	.read = mydriver_read,
    	.write = mydriver_write,
    	.open = mydriver_open,
    	.release = mydriver_release,
    };
    
    static int mydriver_open(struct inode *inode, struct file *file)
    {
    	pr_info("Deviced file was opend.\n");
    	return 0;
    
    }
    
    static int mydriver_release(struct inode *inode, struct file *file)
    {
    	return 0;
    }
    
    
    static int mydriver_read(struct file *flip,
    		char *buf, size_t len, loff_t *off)
    {
    
    	return 0;
    }
    
    static int mydriver_write(struct file *flip,
    		const char *buf, size_t len, loff_t *off)
    {
    	return 0;
    
    }
    
    dev_t dev = 0;
    static struct cdev my_cdev;
    static struct class *dev_class;
    
    static int __init init_hw(void)
    {
    	//\ub514\ubc14\uc774\uc2a4 \ub4f1\ub85d
    	if(( alloc_chrdev_region(&dev, 0, 1, "test_device") < 0))
    	{
    		pr_err("[!]character device was not allocated\n");
    		goto r_unreg;
    
    	}
    	pr_info("[=]%d-%d, was allocated\n", MAJOR(dev), MINOR(dev));
    
    
    	//\ucd08\uae30\ud654
    	cdev_init(&my_cdev, &fops);
    	pr_info("[=]driver was initialized\n");
    	
    
    	//\uc2dc\uc2a4\ud15c\uc5d0 \ucd94\uac00
    	if((cdev_add(&my_cdev, dev, 1)) < 0)
    	{
    		pr_err("[!]cannot add device to kernel\n");
    		goto r_del;
    
    	}
    
    
    	//class \ub9cc\ub4e6.
    	if((dev_class=class_create(THIS_MODULE, "my_class")) == NULL)
    	{
    		pr_err("[!]cannot add class\n");
    		goto r_class;
    	}
    
    
    	if((device_create(dev_class, NULL, dev, NULL, "my_device")) == NULL)
    	{
    
    		pr_err("[!]cannot create device\n");
    		goto r_device;
    	}
    	
    	//gpio 10\ubc88\uc744 \uc0ac\uc6a9.
    	//export\ud558\uc5ec \uac04\ub2e8\ud788 \uc0ac\uc6a9.
    	//\uc785\ub825\uc740 \uac12\uc744 \uc368 \ub123\uc744 \uc218 \uc5c6\uc74c. \ucd9c\ub825\uc73c\ub85c \uc124\uc815.
    	GPIO_irqNumber = gpio_to_irq(GPIO_10_OUT);
    	pr_info("[=]irq %d was assinged\n",GPIO_irqNumber);
    	
    	//interrupt \ub4f1\ub85d \ud544\uc694
    	if (request_irq(GPIO_irqNumber,
    				(void*)gpio_irq_handler,
    				IRQF_TRIGGER_RISING,
    				"my_device",
    				NULL))
    	{
    		pr_err("[!]my_device: cannot register IRQ\n");
    		goto r_gpio;
    	}
    	
    	open_softirq(TEST_SOFT_IRQ, pesudo_interrupt_softirq_handler);
    	pr_info("[=]module was installed\n");
    	return 0;
    r_gpio:
    	gpio_free(GPIO_10_OUT);
    r_device:
    	device_destroy(dev_class,dev);
    
    r_class:
    	class_destroy(dev_class);
    r_del:
    	cdev_del(&my_cdev);
    r_unreg:
    	unregister_chrdev_region(dev,1);
    
    return -1;
    }
    
    static void __exit exit_hw(void) {
    	device_destroy(dev_class,dev);
    	class_destroy(dev_class);
    	cdev_del(&my_cdev);
    	unregister_chrdev_region(dev,1);
    	printk(KERN_INFO "module was removed\n");
    }
    
    
    module_init(init_hw);
    module_exit(exit_hw);
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Eunseong Park (esp-ark.com)");
    MODULE_DESCRIPTION("Hello, world!");
    
    pi@raspberrypi:~/RaspberryDebug/my_driver $ echo "10" > /sys/class/gpio/export
    pi@raspberrypi:~/RaspberryDebug/my_driver $ echo "out" > /sys/class/gpio/gpio10/direction 
    pi@raspberrypi:~/RaspberryDebug/my_driver $ gpio read 10
    1
    pi@raspberrypi:~/RaspberryDebug/my_driver $ echo 0 > /sys/class/gpio/gpio10/value ; echo 1 > /sys/class/gpio/gpio10/value;
    pi@raspberrypi:~/RaspberryDebug/my_driver $ echo 0 > /sys/class/gpio/gpio10/value ; echo 1 > /sys/class/gpio/gpio10/value;
    pi@raspberrypi:~/RaspberryDebug/my_driver $ echo 0 > /sys/class/gpio/gpio10/value ; echo 1 > /sys/class/gpio/gpio10/value;
    
    [  281.496011] my_driver: loading out-of-tree module taints kernel.
    [  281.496218] my_driver: no symbol version for raise_softirq
    [  281.496487] [=]236-0, was allocated
    [  281.496492] [=]driver was initialized
    [  281.496679] [=]irq 54 was assinged
    [  281.496713] [=]module was installed
    [  439.643072] pesudo interreupt occured
    pi@raspberrypi:/sys/class/gpio $ dmesg | tail -10;cat /proc/softirqs 
    [   21.513881] input: Keyboard K480 Consumer Control as /devices/platform/soc/fe201000.serial/tty/ttyAMA0/hci0/hci0:11/0005:046D:B33C.0003/input/input5
    [   21.514017] input: Keyboard K480 System Control as /devices/platform/soc/fe201000.serial/tty/ttyAMA0/hci0/hci0:11/0005:046D:B33C.0003/input/input6
    [   21.514160] hid-generic 0005:046D:B33C.0003: input,hidraw2: BLUETOOTH HID v28.02 Keyboard [Keyboard K480] on e4:5f:01:06:e9:01
    [  281.496011] my_driver: loading out-of-tree module taints kernel.
    [  281.496218] my_driver: no symbol version for raise_softirq
    [  281.496487] [=]236-0, was allocated
    [  281.496492] [=]driver was initialized
    [  281.496679] [=]irq 54 was assinged
    [  281.496713] [=]module was installed
    [  439.643072] pesudo interreupt occured
                        CPU0       CPU1       CPU2       CPU3       
              HI:          1          0          0          0
           TIMER:      18713      21705      20854      19911
          NET_TX:         95         49        315         19
          NET_RX:       1125        324       1051        398
           BLOCK:          0          0          0          0
        IRQ_POLL:          0          0          0          0
         TASKLET:      44263        453        587        288
           SCHED:      17064      20646      19843      18418
         HRTIMER:          0          0          0          0
             RCU:      19242      23191      20816      20212
          (null):          1          0          0          0
    pi@raspberrypi:/sys/class/gpio $ dmesg | tail -10;cat /proc/softirqs 
    [   21.514017] input: Keyboard K480 System Control as /devices/platform/soc/fe201000.serial/tty/ttyAMA0/hci0/hci0:11/0005:046D:B33C.0003/input/input6
    [   21.514160] hid-generic 0005:046D:B33C.0003: input,hidraw2: BLUETOOTH HID v28.02 Keyboard [Keyboard K480] on e4:5f:01:06:e9:01
    [  281.496011] my_driver: loading out-of-tree module taints kernel.
    [  281.496218] my_driver: no symbol version for raise_softirq
    [  281.496487] [=]236-0, was allocated
    [  281.496492] [=]driver was initialized
    [  281.496679] [=]irq 54 was assinged
    [  281.496713] [=]module was installed
    [  439.643072] pesudo interreupt occured
    [  471.316929] pesudo interreupt occured
                        CPU0       CPU1       CPU2       CPU3       
              HI:          1          0          0          0
           TIMER:      18828      21849      21047      20104
          NET_TX:         95         49        321         19
          NET_RX:       1125        324       1063        398
           BLOCK:          0          0          0          0
        IRQ_POLL:          0          0          0          0
         TASKLET:      44459        453        609        288
           SCHED:      17173      20815      20069      18623
         HRTIMER:          0          0          0          0
             RCU:      19350      23343      20917      20386
          (null):          2          0          0          0
    pi@raspberrypi:/sys/class/gpio $ dmesg | tail -10;cat /proc/softirqs 
    [   21.514160] hid-generic 0005:046D:B33C.0003: input,hidraw2: BLUETOOTH HID v28.02 Keyboard [Keyboard K480] on e4:5f:01:06:e9:01
    [  281.496011] my_driver: loading out-of-tree module taints kernel.
    [  281.496218] my_driver: no symbol version for raise_softirq
    [  281.496487] [=]236-0, was allocated
    [  281.496492] [=]driver was initialized
    [  281.496679] [=]irq 54 was assinged
    [  281.496713] [=]module was installed
    [  439.643072] pesudo interreupt occured
    [  471.316929] pesudo interreupt occured
    [  477.954727] pesudo interreupt occured
                        CPU0       CPU1       CPU2       CPU3       
              HI:          1          0          0          0
           TIMER:      18963      22041      21297      20379
          NET_TX:         95         50        325         19
          NET_RX:       1128        326       1068        409
           BLOCK:          0          0          0          0
        IRQ_POLL:          0          0          0          0
         TASKLET:      44749        453        647        288
           SCHED:      17324      21034      20344      18910
         HRTIMER:          0          0          0          0
             RCU:      19496      23548      21158      20547
          (null):          3          0          0          0
    pi@raspberrypi:/sys/class/gpio $ sudo rmmod my_driver 
    pi@raspberrypi:/sys/class/gpio $ dmesg | tail -10;cat /proc/softirqs 
    [  281.496011] my_driver: loading out-of-tree module taints kernel.
    [  281.496218] my_driver: no symbol version for raise_softirq
    [  281.496487] [=]236-0, was allocated
    [  281.496492] [=]driver was initialized
    [  281.496679] [=]irq 54 was assinged
    [  281.496713] [=]module was installed
    [  439.643072] pesudo interreupt occured
    [  471.316929] pesudo interreupt occured
    [  477.954727] pesudo interreupt occured
    [  497.174610] module was removed
                        CPU0       CPU1       CPU2       CPU3       
              HI:          1          0          0          0
           TIMER:      19416      22394      21661      20809
          NET_TX:         95         50        335         19
          NET_RX:       1141        331       1087        409
           BLOCK:          0          0          0          0
        IRQ_POLL:          0          0          0          0
         TASKLET:      45416        479        678        288
           SCHED:      17800      21462      20753      19347
         HRTIMER:          0          0          0          0
             RCU:      19908      23925      21541      20832
          (null):          3          0          0          0
    pi@raspberrypi:/sys/class/gpio $ cat /proc/interrupts 
               CPU0       CPU1       CPU2       CPU3       
     17:          0          0          0          0     GICv2  29 Level     arch_timer
     18:      13237       9026       7126      13623     GICv2  30 Level     arch_timer
     23:        352          0          0          0     GICv2 114 Level     DMA IRQ
     31:       3111          0          0          0     GICv2  65 Level     fe00b880.mailbox
     34:       8655          0          0          0     GICv2 153 Level     uart-pl011
     35:          0          0          0          0     GICv2 169 Level     brcmstb_thermal
     36:      33671          0          0          0     GICv2 158 Level     mmc1, mmc0
     37:      17923          0          0          0     GICv2 144 Level     vc4 firmware kms
     38:          0          0          0          0     GICv2  48 Level     arm-pmu
     39:          0          0          0          0     GICv2  49 Level     arm-pmu
     40:          0          0          0          0     GICv2  50 Level     arm-pmu
     41:          0          0          0          0     GICv2  51 Level     arm-pmu
     42:       8559          0          0          0     GICv2 106 Level     v3d
     44:       1557          0          0          0     GICv2 189 Level     eth0
     45:         52          0          0          0     GICv2 190 Level     eth0
     51:        707          0          0          0     GICv2  66 Level     VCHIQ doorbell
     52:          0          0          0          0     GICv2 175 Level     PCIe PME, aerdrv
     53:       1053          0          0          0  Brcm_MSI 524288 Edge      xhci_hcd
     54:          2          0          0          0  pinctrl-bcm2835  10 Edge      my_device
    IPI0:          0          0          0          0  CPU wakeup interrupts
    IPI1:          0          0          0          0  Timer broadcast interrupts
    IPI2:      12130      21051      27290      15651  Rescheduling interrupts
    IPI3:        785       1597       1554       1937  Function call interrupts
    IPI4:          0          0          0          0  CPU stop interrupts
    IPI5:        793        414        433        246  IRQ work interrupts
    IPI6:          0          0          0          0  completion interrupts
    Err:          0
    

    자 이제 커널을 다시 돌리고 tasklet으로 가자. 드라이버를 언로딩하고 cat /proc/interrupt를 하면 시스템이 어쩃든 죽는다. softirq 문제가 아니라, 인터럽트 핸들러를 해제하지 않아서 죽었다.

    pi@raspberrypi:~/RaspberryDebug/my_driver $ diff my_driver.c my_driver.c.bak
    164d163
    < 	free_irq(GPIO_irqNumber, NULL);