Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.06.2013, 09:52   #1
Косюра
Пользователь
 
Аватар для Косюра
 
Регистрация: 14.01.2011
Сообщений: 74
Восклицание Модуль ядра Linux

Я резервирую буфер (максималь*но 200мб) для худшего случая ...
Но предпочтит*ельнее создать список из буферов (например по 1 мб). Помогите! Не получается.

Модуль:
Код:
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kallsyms.h> 
#include <linux/kprobes.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/time.h>

static struct jprobe jp;
#define PROC_FILE "switches"
struct proc_dir_entry * proc_file;

// Module parameters
// Pidы, за которыми будем следить
#define MAX_PIDS_NUMBER 1024
static int pids[MAX_PIDS_NUMBER];
static int pids_number = 0;
module_param_array(pids, int, &pids_number, S_IRUGO | S_IWUSR);

// Будем следить за всеми pidами
static bool all = false;
module_param(all, bool, S_IRUGO | S_IWUSR);

// Время, после которого стирается информация о переключении
static int buffer_time = 10;
module_param(buffer_time, int, S_IRUGO | S_IWUSR);

// Максимально возможное количество запомненных переключений
static int MAX_LIST = 100000;
module_param(MAX_LIST, int, S_IRUGO);

// Список процессоров, за которыми мы следим
#define MAX_CPUS 128
static int cpus[MAX_CPUS];
static int cpus_number = 0;
module_param_array(cpus, int, &cpus_number, S_IRUGO | S_IWUSR);

// Удалять ли запись после чтения
static bool clear_on_read = true;
module_param(clear_on_read, bool, S_IRUGO | S_IWUSR);

// Реализация списка на базе массива
struct list_entry {
	int pid;
	int next, prev;
	int timestamp;
	int cpu;
	bool already_read;
};
static int list_size = 0;
static int list_head = 0;
static struct list_entry *list;

static inline int round_by_size (int pos) {
	if (pos  >= MAX_LIST) {
		pos -= MAX_LIST;
	}
	return pos;
}

static bool overflow = false;

// Функция для добавления записи о переключении контектса в список
// и, если это потребуется, частичной очистки списка по времени
static int add_list_entry(int pid, int prev, int next, int cpu) {
	struct list_entry entry;
	struct timeval t;
	int i;
	int pos;
	do_gettimeofday(&t);

	for (i = 0; i < list_size; i++) {
		pos = round_by_size(i + list_head);
		if ( ( t.tv_sec - list[ pos ].timestamp > buffer_time )
			|| ( clear_on_read &&  list[pos].already_read ) ) {
			list_head = round_by_size(list_head + 1);
			list_size--;
		} else {
			break;
		}
	}

	// Добавляем новый элемент списка запомненных переключений
	entry.pid = pid;
	entry.prev = prev;
	entry.next = next;
	entry.cpu = cpu;
	entry.timestamp = t.tv_sec;
	list_size++;
	pos = round_by_size(list_size + list_head);
	list[ pos ] = entry;

	if (list_size >= MAX_LIST) {
		if (overflow == false) {
			printk(KERN_WARNING "Buffer overflow! Please, stop the module and resize buffer.\n");
			overflow = true;
		}
		list_head = round_by_size(list_head+1);
		list_size--;
	}

	return 0;
}

// Функция, которая подменяет собой вызов __switch_to
// и, отработав, вызывает ее
struct task_struct *switch_handler(
	struct task_struct *prev,
	struct task_struct *next
) {
	int i;
	pid_t pid_prev = prev->pid;
	pid_t pid_next = next->pid;
	int cpu = task_cpu(next);

	if (cpus_number > 0) {
		for (i = 0; i < cpus_number; i++) {
			if (cpus[i] == cpu) {
				break;
			}
		}
		if (cpus[i] != cpu) {
			jprobe_return();
		}
	}

	if (true == all) {
		add_list_entry(pid_prev, pid_prev, pid_next, cpu);
		add_list_entry(pid_next, pid_prev, pid_next, cpu);
	} else {
		for (i = 0; i < pids_number; i++) {
			if (pids[i] == pid_prev) {
				add_list_entry(pid_prev, pid_prev, pid_next, cpu);
			} else if (pids[i] == pid_next) {
				add_list_entry(pid_next, pid_prev, pid_next, cpu);
			}
		}
	}

	jprobe_return();
	return 0;
}

// Печать списка в proc файл
static void *switches_seq_start (struct seq_file *s, loff_t *pos) {
	int i;
	if (*pos >= list_size) {
		return NULL;
	}
	i = round_by_size(list_head + *pos);

	return &list[ i ];
}

static void *switches_seq_next(struct seq_file *s, void *v, loff_t *pos) {
	int i;
	(*pos)++;
	if (*pos >- list_size) {
		return NULL;
	}
	i = round_by_size(list_head + *pos);
	return &list[ i];
}
Девушка - переменная бинарного типа с рандомным значением
Косюра вне форума Ответить с цитированием
Старый 05.06.2013, 09:53   #2
Косюра
Пользователь
 
Аватар для Косюра
 
Регистрация: 14.01.2011
Сообщений: 74
По умолчанию

Код:
static void switches_seq_stop(struct seq_file *sfile, void *v) {
	
}

static int switches_seq_show(struct seq_file *s, void *v) {
	struct list_entry *entry = (struct list_entry *) v;
	
	if (entry->already_read && clear_on_read) {
		return 0;
	}
	
	seq_printf(s, "%d: %d pid=%d switched to pid=%d on CPU=%d\n",
		entry->timestamp, entry->pid, entry->prev, entry->next, entry->cpu);
	entry->already_read = true;

	return 0;
}

static struct seq_operations switches_seq_ops = {
	.start = switches_seq_start,
	.next = switches_seq_next,
	.stop = switches_seq_stop,
	.show = switches_seq_show,
};

static int switches_proc_open (struct inode *inode, struct file *file) {
	return seq_open(file, &switches_seq_ops);
}

static struct file_operations switches_proc_ops = {
	.owner = THIS_MODULE,
	.open = switches_proc_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = seq_release,
};
// Инициализирующая функция
static int __init
intercept_init(void) {
	kprobe_opcode_t *switch_addr = (kprobe_opcode_t *) kallsyms_lookup_name("__switch_to");
	if (switch_addr == NULL) {
		printk(KERN_ERR "kallsyms_lookup_name could not find address for __switch_to function.\n");
		return -1;
	}

	if ( ( proc_file = create_proc_entry(PROC_FILE, 0, NULL) ) == 0) {
		printk(KERN_ERR "Unable to register proc file\n");
		return -1;
	} else {
		proc_file->proc_fops = &switches_proc_ops;
	}

	list = (struct list_entry *) kmalloc (sizeof( struct list_entry ) * MAX_LIST, GFP_KERNEL);
	if (list == NULL) {
		printk(KERN_ERR "Unable to alloc memory\n");
		return -1;
	}

	printk(KERN_INFO "Context switch interception module loaded.\n");
	printk(KERN_INFO "Address of __switch_to = %x\n", (unsigned int) switch_addr);

	jp.kp.addr = (kprobe_opcode_t *) switch_addr;
	jp.entry = (kprobe_opcode_t *) switch_handler;
	register_jprobe(&jp);
	return 0;
}

module_init(intercept_init);

// Функция, выполняемая при выгрузке модуля
static void __exit
intercept_exit(void)
{
	unregister_jprobe(&jp);
	remove_proc_entry(PROC_FILE, NULL);
	kfree(list);

	printk(KERN_INFO "Context switch interception module unloaded.");
}

module_exit(intercept_exit);
Девушка - переменная бинарного типа с рандомным значением
Косюра вне форума Ответить с цитированием
Старый 05.06.2013, 09:54   #3
Косюра
Пользователь
 
Аватар для Косюра
 
Регистрация: 14.01.2011
Сообщений: 74
По умолчанию

Мейкфайл к нему:
Код:
obj-m := intercept.o

KDIR  := /lib/modules/$(shell uname -r)/build
PWD   := $(shell pwd)


default:
	$(MAKE) -C $(KDIR) M=$(PWD) modules  
clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean
Девушка - переменная бинарного типа с рандомным значением
Косюра вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Компиляция Ядра linux. Ming Общие вопросы C/C++ 17 16.02.2012 17:37
Програмирования ядра Linux 2.6 sovereignua Linux (Ubuntu, Debian, Red Hat, CentOS, Mint) 1 14.07.2009 07:59