2016年10月26日 星期三

Linux kernel - wait_event_interruptible 用法

init_waitqueue_head
wait_event_interruptible
wake_up_interruptible
include/linux/wait.h
/*
 * The below macro ___wait_event() has an explicit shadow of the __ret
 * variable when used from the wait_event_*() macros.
 *
 * This is so that both can use the ___wait_cond_timeout() construct
 * to wrap the condition.
 *
 * The type inconsistency of the wait_event_*() __ret variable is also
 * on purpose; we use long where we can return timeout values and int
 * otherwise.
 */

#define ___wait_event(wq, condition, state, exclusive, ret, cmd)        \
({                                                                      \
        __label__ __out;                                                \
        wait_queue_t __wait;                                            \
        long __ret = ret;       /* explicit shadow */                   \
                                                                        \
        INIT_LIST_HEAD(&__wait.task_list);                              \
        if (exclusive)                                                  \
                __wait.flags = WQ_FLAG_EXCLUSIVE;                       \
        else                                                            \
                __wait.flags = 0;                                       \
                                                                        \
        for (;;) {                                                      \
                long __int = prepare_to_wait_event(&wq, &__wait, state);\
                                                                        \
                if (condition)                                          \
                        break;                                          \
                                                                        \
                if (___wait_is_interruptible(state) && __int) {         \
                        __ret = __int;                                  \
                        if (exclusive) {                                \
                                abort_exclusive_wait(&wq, &__wait,      \
                                                     state, NULL);      \
                                goto __out;                             \
                        }                                               \
                        break;                                          \
                }                                                       \
                                                                        \
                cmd;                                                    \
        }                                                               \
        finish_wait(&wq, &__wait);                                      \
__out:  __ret;                                                          \
})



#define __wait_event_interruptible(wq, condition)                       \
        ___wait_event(wq, condition, TASK_INTERRUPTIBLE, 0, 0,          \
                      schedule())


/**
 * wait_event_interruptible - sleep until a condition gets true
 * @wq: the waitqueue to wait on
 * @condition: a C expression for the event to wait for
 *
 * The process is put to sleep (TASK_INTERRUPTIBLE) until the
 * @condition evaluates to true or a signal is received.
 * The @condition is checked each time the waitqueue @wq is woken up.
 *
 * wake_up() has to be called after changing any variable that could
 * change the result of the wait condition.
 *
 * The function will return -ERESTARTSYS if it was interrupted by a
 * signal and 0 if @condition evaluated to true.
 */
#define wait_event_interruptible(wq, condition)                         \
({                                                                      \
        int __ret = 0;                                                  \
        might_sleep();                                                  \
        if (!(condition))                                               \
                __ret = __wait_event_interruptible(wq, condition);      \
        __ret;                                                          \
})
wait_event_interruptible和wake_up_interruptible小例子:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <asm/uaccess.h>

MODULE_LICENSE("Dual BSD/GPL");

unsigned int globalvar = 0; 
wait_queue_head_t myqueue; 
unsigned int flag = 0; 

static ssize_t myread(struct file *file, char *buf, size_t size, loff_t *loff) 
{ 
        wait_event_interruptible(myqueue , flag != 0); 
        if(copy_to_user(buf, &globalvar, sizeof(int))) 
        { 
                printk("copy to user failed/n"); 
                return -EFAULT; 
        } 
        flag = 0; 
        return sizeof(int); 
} 

static ssize_t mywrite(struct file *file, const char *buf, size_t size, loff_t *loff) 
{ 
        if(copy_from_user(&globalvar, buf, sizeof(int))) 
        { 
                printk("copy from user failed/n"); 
                return -EFAULT ; 
        } 
        wake_up_interruptible(&myqueue); 
        flag = 1; 
        return sizeof(int); 
} 

static const struct file_operations fops = { 
        .read  = myread, 
        .write = mywrite 
}; 

static int __init mod_init(void) 
{ 
        int ret; 
        ret = register_chrdev(133 , "mychar", &fops); 
        if(ret < 0) 
                printk("<0>""register char dev failed/n"); 
        init_waitqueue_head(&myqueue); 
        return 0; 
} 

static void __exit mod_exit(void) 
{ 
        unregister_chrdev(133, "mychar"); 
} 

module_init(mod_init); 
module_exit(mod_exit);
參考來源 http://blog.sina.com.cn/s/blog_4770ef020101h45d.html

Kernel timer 用法

#include <linux/module.h>
#include <linux/init.h>

MODULE_LICENSE("Dual BSD/GPL");

#define TIMEOUT_VALUE (5 * HZ)

static struct timer_list tickfn;

static void sample_timeout(unsigned long arg)
{
    struct timer_list *tick = (struct timer_list *) arg;

    printk(KERN_ALERT "ptr %p\n", tick);

    mod_timer(tick, jiffies + TIMEOUT_VALUE);
}

static int __init sample_init(void)
{
    printk(KERN_ALERT "driver loaded\n");

    init_timer(&tickfn);
    tickfn.function = sample_timeout;
    tickfn.data = (unsigned long) &tickfn;
    tickfn.expires = jiffies + TIMEOUT_VALUE;
    add_timer(&tickfn);

    return 0;
}

static void __exit sample_exit(void)
{
    int ret;
    ret = del_timer_sync(&tickfn);

    printk(KERN_ALERT "driver unloaded (%d)\n", ret);
}

module_init(sample_init);
module_exit(sample_exit);

2016年10月7日 星期五

中國移動 中國及香港兩地 4G上網卡

中國內地及香港兩地流動數據儲值卡
-          享有1.2GB的4G漫遊數據,可用120日。
-          內附一張預付儲值卡及說明書。
-          使用範圍:中國內地及香港。
-          插卡即可使用,無須登記。
-          可轉換至NANO、MICRO、NORMAL SIM,無需剪卡。
-          有效日期至2017年06月30日,開卡後可用120日。
 
-         注意事項:
  1)     請在中國內地或香港插入和啟用此卡。
  2)     所有預付卡為一次性使用儲值卡,不可充值。
  3)     用戶若持有鎖機的手機,必須請電信公司解鎖手機,方能使用此SIM卡。
  4)      中國內地4G數據服務適用於中國移動4G TDD-LTE制式網絡,而服務須配合適合的上網設備。
  5)      如客戶在香港身處4G覆蓋以外地區,仍會透過2G EDGE/3G網絡為客戶提供服務。
  6)      於中國內地時數據用量只適用於中國移動2G EDGE/3G TD-SCDMA/4G TDD-LTE。
  7)      有效期內,數據用量累計達中港共用數據用量上限後,數據服務將會終止,無法再開通使  用。
  8)      服務不支援話音和短訊服務。
  9)   亞太電信的CDMA系統手機無法使用此卡。

https://tw.bid.yahoo.com/item/CiCiBiYi-%E5%85%A8%E7%90%83%E7%B6%B2%E5%8D%A1%E5%B0%8F%E8%88%96-%E4%B8%AD%E5%9C%8B%E7%A7%BB%E5%8B%95%E9%A6%99%E6%B8%AF4G-%E4%B8%AD%E5%9C%8B%E5%8F%8A%E9%A6%99%E6%B8%AF%E5%85%A9-100256222635