(Linux内核代码解答)这是一段应用程序 求详细解答

zmp55555 2014-12-18 10:34:05
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, char **argv)
{
int on;
int led_no;
int fd;
char buffer[6] = "zengm";

if (argc != 3 || sscanf(argv[1], "%d", &led_no) != 1 || sscanf(argv[2],"%d", &on) != 1 ||
on < 0 || on > 1 || led_no < 0 || led_no > 3) {
fprintf(stderr, "Usage: leds led_no 0|1\n");
exit(1);
}

fd = open("/dev/leds", O_RDWR);
if (fd < 0) {
perror("open device leds");
exit(1);
}

ioctl(fd, led_no, on);
#if 0
if(write(fd, buffer, 6))
printf("my write error %d\n",errno);

if(read(fd, buffer, 6))
printf("my read error %d\n",errno);

printf("%s\n", buffer);
#endif

close(fd);

return 0;
}


...全文
185 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
david-yue 2014-12-28
  • 打赏
  • 举报
回复
应用程序main函数中open、ioctl、read、write就可以调用到内核相对应的函数,你的驱动里实现了这几个函数: static struct file_operations dev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = sbc2440_leds_ioctl, .read = sbc2440_leds_read, .write = sbc2440_leds_write, .open = sbc2440_leds_open, }; 内核模块在加载和下载的时候,会调用 dev_init和dev_exit函数
wfwater 2014-12-21
  • 打赏
  • 举报
回复
ioctl就是用户空间进入内核空间的一个途径,具体实现看linux 设备驱动
羽飞 2014-12-18
  • 打赏
  • 举报
回复
ioctl是一个系统调用,系统调用最终都会跑到内核中,内核会调用驱动注册的回调函数 在3.13版本内核中,楼主可以看到内核中fs/ioctl.c中有下面的代码: SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg) 这里就是内核定义了一个对应的系统调用的实现:ioctl
zmp55555 2014-12-18
  • 打赏
  • 举报
回复
主要是主要流程是怎么样的 怎么样从main进入到内核驱动 这个过程是怎么实现的
zmp55555 2014-12-18
  • 打赏
  • 举报
回复
附上内核驱动代码
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/kthread.h>
#include <linux/wait.h>
#if 1
#include </usr/src/linux-2.6.38/arch/arm/plat-samsung/include/plat/gpio-cfg.h>

#include </usr/src/linux-2.6.38/arch/arm/mach-s3c64xx/include/mach/map.h>
#include </usr/src/linux-2.6.38/arch/arm/mach-s3c64xx/include/mach/regs-clock.h>
#include </usr/src/linux-2.6.38/arch/arm/mach-s3c64xx/include/mach/regs-gpio.h>
#include </usr/src/linux-2.6.38/arch/arm/mach-s3c64xx/include/mach/gpio-bank-e.h>
#include </usr/src/linux-2.6.38/arch/arm/mach-s3c64xx/include/mach/gpio-bank-k.h>
#endif
#define DEVICE_NAME "leds" 

static wait_queue_head_t  wq;

static char condition = 0;

static unsigned int OnOff = 0;

static long sbc2440_leds_ioctl(struct file *filp, unsigned long ledNum, unsigned int OnOff_data) 
{ 
#if 0
    switch(OnOff) 
    { 
        unsigned tmp; 
        case 0: case 1:
            if (ledNum > 3) 
            { 
                return -EINVAL; 
            }
            tmp = readl(S3C64XX_GPKDAT); 
            tmp &= ~(1 << (4 + ledNum)); 
            tmp |= ( (!OnOff) << (4 + ledNum) ); 
            writel(tmp, S3C64XX_GPKDAT); 
            return 0; 
        default: 
            return -EINVAL; 
    } 
#endif

    OnOff = OnOff_data;

    condition = 1;
    wake_up(&wq);

    return 0;

}

char string[6]="hello";

static int sbc2440_leds_read(struct file * filp, char * buffer, size_t size , loff_t * p) 
{ 
    memcpy(buffer, string, size);
    return 0;
}

static int sbc2440_leds_write(struct file * filp, char * buffer, size_t size , loff_t * p) 
{ 
    printk(KERN_INFO "%s\n", buffer); 
    return 0;
}

#if 0 
static void TimerCallbackFun(unsigned long data)
{
    char OnOff = 0;

    mod_timer((timer_list * )data, jiffies + 1*HZ);

    tmp = readl(S3C64XX_GPKDAT); 
    tmp &= ~(1 << (4 + 1)); 
    tmp |= ( (!OnOff) << (4 + 1) ); 
    writel(tmp, S3C64XX_GPKDAT); 
    return 0; 

}

#endif
static int LedCtrl(void * data)
{
    int              tmp = 0;

    for(;;)
    {
        wait_event_interruptible(wq, condition);

        if(condition)
        {
            // ctrl leds
            tmp = readl(S3C64XX_GPKDAT); 
            tmp &= ~(1 << (4 + 1)); 
            tmp |= ( (!OnOff) << (4 + 1) ); 
            writel(tmp, S3C64XX_GPKDAT); 

            condition = 0;
        }
    }

    return 0;
}

static int sbc2440_leds_open(struct file * filp) 
{ 
    printk(KERN_INFO "open driver!\n"); 

#if 0
    static struct timer_list timer;

    init_timer(&timer);

    timer.function = TimerCallbackFun;
    timer.data      = &timer;
    timer.expires  = jiffies + 1*HZ;

    add_timer(&timer);
#endif
    init_waitqueue_head(&wq);

    kthread_run(LedCtrl, NULL, "LED_CTRL");

    return 0;
}

static struct file_operations dev_fops = 
{ 
    .owner = THIS_MODULE, 
    .unlocked_ioctl = sbc2440_leds_ioctl, 
    .read = sbc2440_leds_read,
    .write = sbc2440_leds_write,
    .open = sbc2440_leds_open,
}; 

static struct miscdevice misc = 
{ 
    .minor = MISC_DYNAMIC_MINOR, 
    .name = DEVICE_NAME, 
    .fops = &dev_fops, 
}; 

static int __init dev_init(void) 
{ 
    int ret; 
    #if 1
    {
        unsigned tmp; 
        tmp = readl(S3C64XX_GPKCON); 
        tmp = (tmp & ~(0xffffU<<16))|(0x1111U<<16); 
        writel(tmp, S3C64XX_GPKCON); 
        tmp = readl(S3C64XX_GPKDAT); 
        tmp |= (0xF << 4); 
        writel(tmp, S3C64XX_GPKDAT); 
    }
    #endif

    ret = misc_register(&misc); 
    printk (DEVICE_NAME"\tinitialized\n"); 
    
    return ret; 
}

static void __exit dev_exit(void) 
{ 
    misc_deregister(&misc); 
}

module_init(dev_init); 
module_exit(dev_exit); 

MODULE_LICENSE("GPL"); 
MODULE_AUTHOR("Softi Inc.");
杨六 2014-12-18
  • 打赏
  • 举报
回复
路过,学习一下,建议可以看下Linux内核设计与实现这本书,里面有基础的东西可以让你大致对linux内核有个理解。

4,438

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧