Rumah > Tutorial sistem > LINUX > Penjelasan terperinci tentang penggunaan pemasa kernel Linux

Penjelasan terperinci tentang penggunaan pemasa kernel Linux

WBOY
Lepaskan: 2024-02-09 13:50:27
ke hadapan
1047 orang telah melayarinya

Pemasa kernel LINUX ialah mekanisme yang digunakan oleh kernel untuk mengawal penjadualan dan pelaksanaan fungsi tertentu pada masa tertentu pada masa hadapan (berdasarkan jiffies). Pelaksanaan mekanisme ini terletak dalam fail dan kernel/timer.c.

Penjelasan terperinci tentang penggunaan pemasa kernel Linux

Fungsi berjadual mesti dilaksanakan secara tak segerak Ia serupa dengan "gangguan perisian" dan berada dalam konteks bukan proses. Oleh itu, fungsi penjadualan mesti mematuhi peraturan berikut:

  1. Tanpa penunjuk semasa, tiada akses kepada ruang pengguna dibenarkan. Oleh kerana tiada konteks proses, kod yang berkaitan tidak mempunyai sambungan kepada proses yang terganggu.
  2. Tidur atau fungsi dan jadual yang mungkin menyebabkan tidur tidak boleh dilaksanakan.
  3. Sebarang struktur data yang diakses harus dilindungi daripada akses serentak untuk mengelakkan keadaan perlumbaan.

Sebaik sahaja fungsi penjadualan pemasa kernel dijalankan sekali, ia tidak akan dijalankan lagi (bersamaan dengan log keluar automatik). Walau bagaimanapun, adalah mungkin untuk dijalankan secara berkala dengan menjadualkan semula dirinya dalam fungsi yang dijadualkan.

Dalam sistem SMP, fungsi penjadualan sentiasa berjalan pada CPU yang sama di mana ia didaftarkan untuk mendapatkan lokaliti cache sebanyak mungkin.

API Pemasa

Struktur data pemasa kernel

struct timer_list {
  struct list_head entry;

  unsigned long expires;
  void (*function)(unsigned long);
  unsigned long data;

  struct tvec_base *base;
  /* ... */
};
Salin selepas log masuk

Medan tamat tempoh mewakili nilai jiffies yang pemasa dijangka akan laksanakan Apabila nilai jiffies dicapai, fungsi fungsi akan dipanggil dan data akan dihantar sebagai parameter. Apabila pemasa didaftarkan pada kernel, medan entri digunakan untuk menyambung pemasa ke senarai terpaut kernel. Medan asas digunakan secara dalaman oleh pelaksanaan kernel.
Ambil perhatian bahawa nilai tamat tempoh ialah 32 bit, kerana pemasa kernel tidak digunakan untuk titik masa hadapan yang panjang.

Permulaan

Sebelum menggunakan struct timer_list, anda perlu memulakan struktur data untuk memastikan semua medan ditetapkan dengan betul. Terdapat dua kaedah permulaan.
Kaedah 1:
DEFINE_TIMER(nama_pemasa, nama_fungsi, nilai_luput, data);
Makro ini secara statik akan mencipta pemasa kernel bernama timer_name dan memulakan fungsinya, tamat tempoh, nama dan medan asas.

Kaedah 2:

struct timer_list mytimer;
setup_timer(&mytimer, (*function)(unsigned long), unsigned long data);
mytimer.expires = jiffies + 5*HZ;
方法3:
struct timer_list mytimer;
init_timer(&mytimer);  
 mytimer ->timer.expires = jiffies + 5*HZ;
 mytimer ->timer.data = (unsigned long) dev;
 mytimer ->timer.function = &corkscrew_timer; /* timer handler */
Salin selepas log masuk

Tentukan pemasa secara dinamik melalui init_timer(), dan kemudian ikat alamat dan parameter fungsi pemprosesan ke senarai_pemasa,
Ambil perhatian bahawa tidak kira kaedah mana yang digunakan untuk memulakan, intipatinya hanyalah untuk memberikan nilai kepada medan, jadi medan tamat tempoh, fungsi dan data boleh diubah suai terus sebelum menjalankan add_timer().
Untuk definisi makro dan fungsi di atas, lihat include/linux/timer.h.

Daftar

Untuk pemasa berkuat kuasa, ia mesti disambungkan ke senarai terpaut khusus dalam kernel Ini boleh dicapai melalui add_timer(struct timer_list *timer).

Daftar semula

Untuk mengubah suai masa penjadualan pemasa, anda boleh memanggil mod_timer(struct timer_list *timer, unsigned long expired). mod_timer() akan mendaftarkan semula pemasa kepada kernel tanpa mengira sama ada fungsi pemasa telah dijalankan.

Log Keluar

Untuk menyahdaftar pemasa, anda boleh menggunakan del_timer(struct timer_list *timer) atau del_timer_sync(struct timer_list *timer). Antaranya, del_timer_sync digunakan pada sistem SMP (pada sistem bukan SMP, ia sama dengan del_timer Apabila fungsi pemasa untuk dilog keluar berjalan pada CPU lain, del_timer_sync() akan menunggu sehingga ia selesai berjalan, jadi ini). fungsi akan hibernate. Di samping itu, ia juga harus dielakkan daripada bersaing untuk kunci yang sama dengan fungsi yang dijadualkan. Untuk pemasa yang telah dijalankan dan belum mendaftar semula dirinya, fungsi nyahdaftar sebenarnya tiada kaitan.

int timer_pending(const struct timer_list *timer)
Fungsi ini digunakan untuk menentukan sama ada pemasa telah ditambahkan pada senarai kernel menunggu untuk dijadualkan untuk dijalankan. Ambil perhatian bahawa apabila fungsi pemasa akan dijalankan, kernel akan memadam pemasa yang sepadan daripada senarai dipautkan kernel (bersamaan dengan log keluar)

一个简单的例子

#include 
\#include 
\#include 

struct timer_list mytimer;

static void myfunc(unsigned long data)
{
    printk("%s/n", (char *)data);
    mod_timer(&mytimer, jiffies + 2*HZ);
}

static int __init mytimer_init(void)
{
    setup_timer(&mytimer, myfunc, (unsigned long)"Hello, world!");
    mytimer.expires = jiffies + HZ;
    add_timer(&mytimer);

​    return 0;
}

static void __exit mytimer_exit(void)
{
    del_timer(&mytimer);
}

module_init(mytimer_init);
module_exit(mytimer_exit);

例子2
static struct timer_list power_button_poll_timer;

static void power_button_poll(unsigned long dummy)
{
 if (gpio_line_get(N2100_POWER_BUTTON) == 0) {
 ctrl_alt_del();
 return;
 }

 power_button_poll_timer.expires = jiffies + (HZ / 10);
 add_timer(&power_button_poll_timer);
}


static void __init n2100_init_machine(void)
{
;
;
 init_timer(&power_button_poll_timer);
 power_button_poll_timer.function = power_button_poll;
 power_button_poll_timer.expires = jiffies + (HZ / 10);
 add_timer(&power_button_poll_timer);
}
Salin selepas log masuk

例子3

设备open时初始化和注册定时器

static int corkscrew_open(struct net_device *dev)

{
;
;
 init_timer(&vp->timer);  
 vp->timer.expires = jiffies + media_tbl[dev->if_port].wait;
 vp->timer.data = (unsigned long) dev;
 vp->timer.function = &corkscrew_timer; /* timer handler */
 add_timer(&vp->timer);
:
;
}
定时器超时处理函数,对定时器的超时时间重新赋值

static void corkscrew_timer(unsigned long data)
{
;
;
  vp->timer.expires = jiffies + media_tbl[dev->if_port].wait;
  add_timer(&vp->timer);
;
;
}

设备close时删除定时器
static int corkscrew_close(struct net_device *dev)
{
 ;
;
 del_timer(&vp->timer);
;
;
}


例子4

本例子用DEFINE_TIMER静态创建定时器

\#include 
\#include 
\#include 
\#include 
\#include 
\#include 

static void ledtrig_ide_timerfunc(unsigned long data);

DEFINE_LED_TRIGGER(ledtrig_ide);
static DEFINE_TIMER(ledtrig_ide_timer, ledtrig_ide_timerfunc, 0, 0);
static int ide_activity;
static int ide_lastactivity;

void ledtrig_ide_activity(void)
{
    ide_activity++;
    if (!timer_pending(&ledtrig_ide_timer))
       mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
}
EXPORT_SYMBOL(ledtrig_ide_activity);

static void ledtrig_ide_timerfunc(unsigned long data)
{
    if (ide_lastactivity != ide_activity) {
       ide_lastactivity = ide_activity;
       led_trigger_event(ledtrig_ide, LED_FULL);
       mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
    } else {
       led_trigger_event(ledtrig_ide, LED_OFF);
    }
}

static int __init ledtrig_ide_init(void)
{
    led_trigger_register_simple("ide-disk", &ledtrig_ide);
    return 0;
}

static void __exit ledtrig_ide_exit(void)
{
    led_trigger_unregister_simple(ledtrig_ide);
}

module_init(ledtrig_ide_init);
module_exit(ledtrig_ide_exit);

MODULE_AUTHOR("Richard Purdie ");
MODULE_DESCRIPTION("LED IDE Disk Activity Trigger");
MODULE_LICENSE("GPL");
Salin selepas log masuk

Atas ialah kandungan terperinci Penjelasan terperinci tentang penggunaan pemasa kernel Linux. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:lxlinux.net
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan