我玩过内核抢占。 想法是看看较高优先级 RT 进程如何抢占内核中运行的较低优先级进程。 为了进入内核,使用
read()
系统调用回调创建了简单的模块:
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/sched.h>
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
static dev_t my_dev;
static struct cdev *my_cdev;
// sysfs class structure
static struct class *mychardev_class = NULL;
// callback for read() system call
static ssize_t my_read(struct file *file, char __user *buf,size_t count,loff_t *ppos)
{
int len = 20;
if(*ppos > 0)
{
return 0;
}
msleep(10000);
if (copy_to_user(buf, "hello from demo_dev ", len)) {
return -EFAULT;
} else {
*ppos +=len;
return len;
}
}
static struct file_operations my_fops =
{
.owner = THIS_MODULE,
.read = my_read,
};
static int __init hello_init (void)
{
my_dev = MKDEV(400,0);
// create sysfs class
mychardev_class = class_create(THIS_MODULE, "mychardev");
register_chrdev_region(my_dev,1,"demo");
my_cdev=cdev_alloc();
if(!my_cdev)
{
printk (KERN_ERR "cdev alloc error.\n");
return -1;
}
my_cdev->ops = &my_fops;
my_cdev->owner = THIS_MODULE;
cdev_init(my_cdev, &my_fops);
if(cdev_add(my_cdev,my_dev,1))
{
printk (KERN_ERR "cdev add error.\n");
return -1;
}
// create device node /dev/demo_dev
device_create(mychardev_class, NULL, my_dev, NULL, "demo_dev");
printk (KERN_INFO "demo_dev added.\n");
return 0;
}
static void __exit hello_exit (void)
{
device_destroy(mychardev_class, my_dev);
cdev_del(my_cdev);
class_unregister(mychardev_class);
class_destroy(mychardev_class);
unregister_chrdev_region(my_dev, 1);
printk (KERN_INFO "demo_dev removed.\n");
}
module_init (hello_init);
module_exit (hello_exit);
MODULE_LICENSE("GPL");
为了测试它,使用
SCHED_FIFO
策略创建了 2 个线程,一个具有较高优先级 50,一个具有较低优先级 30,2 秒后创建:
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int off;
void *hi_prio(void *p)
{
printf("thread1 start time=%ld\n",time(NULL)-off);
sleep(3);
printf("thread1 stop time=%ld\n",time(NULL)-off);
return NULL;
}
void *low_prio(void *p)
{
int ret;
char buf[20];
int fd=open("/dev/demo_dev",O_RDONLY); // #mknod /dev/demo c 400 0
printf("thread2 start time=%ld\n",time(NULL)-off);
ret = read(fd,buf,20);
printf("thread2 read:%s\n");
printf("thread2 stop time=%ld\n",time(NULL)-off);
return NULL;
}
int main()
{
pthread_t t1,t2,t3;
pthread_attr_t attr;
struct sched_param param;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
param.sched_priority = 50;
pthread_attr_setschedparam(&attr, ¶m);
off = time(NULL);
pthread_create(&t1,&attr,hi_prio,NULL);
param.sched_priority = 30;
pthread_attr_setschedparam(&attr, ¶m);
sleep(2);
pthread_create(&t2,&attr,low_prio,NULL);
sleep(20);
printf("main thread stop time=%ld\n",time(NULL)-off);
puts("end test");
return 0;
}
高优先级线程休眠了3秒,结果符合预期:
thread1 start time=0
thread2 start time=2
thread1 stop time=3
thread2 read:hello from demo_dev
thread2 stop time=13
main thread stop time=22
end test
但是当我改变困倦等待
msleep(10000);
与忙碌等待时:
mdelay(5000); // busy-wait for 5 seconds
schedule();
mdelay(5000); // busy-wait for 5 seconds
高优先级线程在7秒后唤醒。
thread1 start time=0
thread2 start time=2
thread1 stop time=7
thread2 read:hello from demo_dev
thread2 stop time=12
main thread stop time=22
end test
我想原因是因为只配置了自愿抢占:
CONFIG_PREEMPT_VOLUNTARY=y
#CONFIG_PREEMPT is not set
进程不能在内核代码中被抢占,除非它显式调用
schedule()
或阻塞(睡眠)?
我假设其他调度策略会产生相同的结果?
您只启用了自愿抢占,
CONFIG_PREEMPT is not set
,这意味着当内核执行时syscall
当它变得可运行时,另一个更高优先级的进程无法在同一个CPU上中断它。