[Linux 구동] 제7 장 시간 지연 및 지연 작업 (예 상세 설명 1)
모듈 방법
jit.c
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <asm/hardirq.h>
#include <linux/sched.h> //schedule()
/*
* This module is a silly one: it only embeds short code fragments
* that show how time delays can be handled in the kernel.
*/
int delay = HZ; /* s3c24x0 HZ= 200*/
module_param(delay, int, 0);
/* use these as data pointers, to implement four files in one function */
enum jit_files {
JIT_BUSY,
JIT_SCHED,
JIT_QUEUE,
JIT_SCHEDTO
};
/*
, , , , , , , , , , , , 。 , , 。 :
*/
int jit_fn(char *buf, char **start, off_t offset,int len, int *eof, void *data)
{
unsigned long j0, j1; /* jiffies */
wait_queue_head_t wait;
init_waitqueue_head (&wait);
j0 = jiffies;
j1 = j0 + delay;
/* , jiffies */
switch((long)data) {
case JIT_BUSY: //
while (time_before(jiffies, j1))
cpu_relax();
break;
case JIT_SCHED: //
while (time_before(jiffies, j1)) {
schedule();
}
break;
case JIT_QUEUE: //
wait_event_interruptible_timeout(wait, 0, delay);
break;
case JIT_SCHEDTO:
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout (delay);
break;
}
j1 = jiffies; /* actual value after we delayed */
len = sprintf(buf, "%9li %9li
", j0, j1);
*start = buf;
return len;
}
/*
* This file, on the other hand, returns the current time forever
*/
int jit_currentime(char *buf, char **start, off_t offset,int len, int *eof, void *data)
{
struct timeval tv1;
struct timespec tv2;
unsigned long j1;
u64 j2;
/* get them four */
j1 = jiffies;
j2 = get_jiffies_64();
do_gettimeofday(&tv1);// struct timeval
tv2 = current_kernel_time();// , struct timeval
/* print */
len=0;
len += sprintf(buf,"0x%08lx 0x%016Lx %10i.%06i
"
"%40i.%09i
",
j1, j2,
(int) tv1.tv_sec, (int) tv1.tv_usec,
(int) tv2.tv_sec, (int) tv2.tv_nsec);
*start = buf; /*if you want currentime to output only onec ,disable this line!*/
return len;
}
/*
* The timer example follows
*/
int tdelay = 10;
module_param(tdelay, int, 0);
/* This data structure used as "data" for the timer and tasklet functions */
struct jit_data {
struct timer_list timer;
struct tasklet_struct tlet;
int hi; /* tasklet or tasklet_hi */
wait_queue_head_t wait;
unsigned long prevjiffies;
unsigned char *buf;
int loops;
};
#define JIT_ASYNC_LOOPS 5
void jit_timer_fn(unsigned long arg)
{
struct jit_data *data = (struct jit_data *)arg;
unsigned long j = jiffies;
data->buf += sprintf(data->buf, "%9li %3li %i %6i %i %s
",
j, j - data->prevjiffies, in_interrupt() ? 1 : 0,
current->pid, smp_processor_id(), current->comm);
if (--data->loops) {
data->prevjiffies = j;
mod_timer(&data->timer, data->timer.expires+tdelay);
} else {
wake_up_interruptible(&data->wait);
}
}
/* the /proc function: allocate everything to allow concurrency */
int jit_timer(char *buf, char **start, off_t offset,int len, int *eof, void *unused_data)
{
struct jit_data *data;
char *buf2 = buf;
unsigned long j = jiffies;
data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
init_timer(&data->timer);
init_waitqueue_head (&data->wait);
/* write the first lines in the buffer */
buf2 += sprintf(buf2, " time delta inirq pid cpu command
");
buf2 += sprintf(buf2, "%9li %3li %i %6i %i %s
",
j, 0L, in_interrupt() ? 1 : 0,
current->pid, smp_processor_id(), current->comm);
/* fill the data for our timer function */
data->prevjiffies = j;
data->buf = buf2;
data->loops = JIT_ASYNC_LOOPS;
/* register the timer */
data->timer.data = (unsigned long)data;
data->timer.function = jit_timer_fn;
data->timer.expires = j + tdelay; /* parameter */
add_timer(&data->timer);
/* wait for the buffer to fill */
wait_event_interruptible(data->wait, !data->loops);
if (signal_pending(current))
return -ERESTARTSYS;
buf2 = data->buf;
kfree(data);
*eof = 1;
return buf2 - buf;
}
void jit_tasklet_fn(unsigned long arg)
{
struct jit_data *data = (struct jit_data *)arg;
unsigned long j = jiffies;
data->buf += sprintf(data->buf, "%9li %3li %i %6i %i %s
",
j, j - data->prevjiffies, in_interrupt() ? 1 : 0,
current->pid, smp_processor_id(), current->comm);
if (--data->loops) {
data->prevjiffies = j;
if (data->hi)
tasklet_hi_schedule(&data->tlet);
else
tasklet_schedule(&data->tlet);
} else {
wake_up_interruptible(&data->wait);
}
}
/* the /proc function: allocate everything to allow concurrency */
int jit_tasklet(char *buf, char **start, off_t offset,int len, int *eof, void *arg)
{
struct jit_data *data;
char *buf2 = buf;
unsigned long j = jiffies;//
long hi = (long)arg;
data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
init_waitqueue_head (&data->wait);
/* write the first lines in the buffer */
buf2 += sprintf(buf2, " time delta inirq pid cpu command
");//
buf2 += sprintf(buf2, "%9li %3li %i %6i %i %s
",
j, 0L, in_interrupt() ? 1 : 0,
current->pid, smp_processor_id(), current->comm);
/* fill the data for our tasklet function */
data->prevjiffies = j;
data->buf = buf2;
data->loops = JIT_ASYNC_LOOPS;
/* register the tasklet */
tasklet_init(&data->tlet, jit_tasklet_fn, (unsigned long)data);
data->hi = hi;
if (hi)
tasklet_hi_schedule(&data->tlet);
else
tasklet_schedule(&data->tlet);
/* wait for the buffer to fill */
wait_event_interruptible(data->wait, !data->loops);
if (signal_pending(current))
return -ERESTARTSYS;
buf2 = data->buf;
kfree(data);
*eof = 1;
return buf2 - buf;
}
int __init jit_init(void) //
{
create_proc_read_entry("currentime", 0, NULL, jit_currentime, NULL);
create_proc_read_entry("jitbusy", 0, NULL, jit_fn, (void *)JIT_BUSY); // data jit_fn
create_proc_read_entry("jitsched",0, NULL, jit_fn, (void *)JIT_SCHED);
create_proc_read_entry("jitqueue",0, NULL, jit_fn, (void *)JIT_QUEUE);
create_proc_read_entry("jitschedto", 0, NULL, jit_fn, (void *)JIT_SCHEDTO);
create_proc_read_entry("jitimer", 0, NULL, jit_timer, NULL);
create_proc_read_entry("jitasklet", 0, NULL, jit_tasklet, NULL);
create_proc_read_entry("jitasklethi", 0, NULL, jit_tasklet, (void *)1);
return 0; /* success */
}
void __exit jit_cleanup(void)//
{
remove_proc_entry("currentime", NULL);
remove_proc_entry("jitbusy", NULL);
remove_proc_entry("jitsched", NULL);
remove_proc_entry("jitqueue", NULL);
remove_proc_entry("jitschedto", NULL);
remove_proc_entry("jitimer", NULL);
remove_proc_entry("jitasklet", NULL);
remove_proc_entry("jitasklethi", NULL);
}
module_init(jit_init); //insmod jit.ko
module_exit(jit_cleanup); //rmmod jit.ko
MODULE_AUTHOR("Alessandro Rubini ( modified by tekkaman )");
MODULE_LICENSE("Dual BSD/GPL");
Makefile
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
obj-m := jit.o
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
.PHONY: modules modules_install clean
테스트:
root@ubuntu: ~ / 데스크 톱 / jit \ # make
root@ubuntu: ~ / 데스크 톱 / jit \ # insmod jit.ko
root@ubuntu: ~ / 데스크 톱 / jit \ # lsmod //조회 설치 완료
그 중에서 파일 currentime, jitbusy, jitsched, jitqueue, jitschedto, jitimer, jitasklet, jitasklethi 는 모두 모듈 jit 로 만 들 어 졌 습 니 다.
root@ubuntu: ~ / 데스크 톱 / jit \ # head -6 /proc/currentime //currentime 파일 의 앞 여섯 줄 을 조회 합 니 다 (currentime 는 jit 프로그램 을 만 듭 니 다)
/ * 되 돌아 오 는 값 은: 현재 jiffies 와 jiffies64 값, 16 진수 형식 으로. 와 같다, 흡사...gettime of day 가 돌아 오 는 같은 현재 시간. currentkernel_time 이 돌아 오 는 timespec. * /
0x004e4a3e 0x00000001004e4a3e 1334565617.514572 1334565617.511113437 0x004e4a3e 0x00000001004e4a3e 1334565617.514575 1334565617.511113437 0x004e4a3e 0x00000001004e4a3e 1334565617.514576 1334565617.511113437
root@ubuntu: ~ / 데스크 톱 / jit \ # dd bs = 20 count = 5 < / proc / jitbusy //dd 명령 참조 【 보충 1 】 5183602 5183852 5183852 5184102 5184102 5184352 5184352 5184602 5184602 5184852 5 + 0 의 읽 기 기록 을 기 록 했 습 니 다. 5 + 0 의 쓰기 100 바이트 (100 B) 가 복사 되 었 습 니 다. 4.99935 초, 0.0 kB / 초 입 니 다.
root@ubuntu: ~ / 데스크 톱 / jit \ # dd bs = 20 count = 5 < / proc / jitsched 5198924 5199174 5199174 5199424 5199424 5199674 5199674 5199924 5199924 52000174 5 + 0 의 읽 기 기록 5 + 0 의 쓰기 100 바이트 (100 B) 가 복사 되 었 습 니 다. 4.99645 초, 0.0 kB / 초 입 니 다.
root@ubuntu: ~ / 데스크 톱 / jit \ # dd bs = 20 count = 5 < / proc / jitqueue 5205914 5206164 5206164 5206414 5206414 5206664 5206664 5206914 5206914 5207164 5 + 0 의 읽 기 기록 5 + 0 의 쓰기 100 바이트 (100 B) 가 복사 되 었 습 니 다. 4.99969 초, 0.0 kB / 초 입 니 다.
root@ubuntu: ~ / 데스크 톱 / jit \ # dd bs = 20 count = 5 < / proc / jitschedto 5212110 5212360 5212360 5212610 5212610 5212860 5212860 5213110 5213110 5213360 5 + 0 의 읽 기 기록 5 + 0 의 쓰기 100 바이트 (100 B) 가 복사 되 었 습 니 다. 4.99915 초, 0.0 kB / 초 입 니 다.
root@ubuntu: ~ / 데스크 톱 / jit \ # cat / proc / jitimer //inirp 중단 되 었 습 니까? time delta inirq pid cpu command 5226700 0 0 4625 3 cat 5226710 10 1 0 3 kworker/0:1 5226720 10 1 0 3 kworker/0:1 5226730 10 1 0 3 kworker/0:1 5226740 10 1 0 3 kworker/0:1 5226750 10 1 0 3 kworker/0:1
root@ubuntu: ~ / 데스크 톱 / jit \ # cat / proc / jitasklet time delta inirq pid cpu command 5236006 0 0 4626 2 cat 5236006 0 1 13 2 ksoftirqd/2 5236006 0 1 13 2 ksoftirqd/2 5236006 0 1 13 2 ksoftirqd/2 5236006 0 1 13 2 ksoftirqd/2 5236006 0 1 13 2 ksoftirqd/2
root@ubuntu: ~ / 데스크 톱 / jit \ # cat / proc / jitasklethi time delta inirq pid cpu command 5241403 0 0 4627 2 cat 5241403 0 1 13 2 ksoftirqd/2 5241403 0 1 13 2 ksoftirqd/2 5241403 0 1 13 2 ksoftirqd/2 5241403 0 1 13 2 ksoftirqd/2 5241403 0 1 13 2 ksoftirqd/2
【 보충 1 】 dd 는 Linux / UNIX 에서 매우 유용 한 명령 으로 지정 한 크기 의 블록 으로 파일 을 복사 하고 복사 하 는 동시에 지정 한 변환 을 하 는 역할 을 합 니 다.dd 의 주요 옵션:
숫자 를 지정 한 곳 에 다음 문자 의 끝 에 해당 하 는 숫자 를 곱 하면:
b=512, c=1, k=1024, w=2, xm=number m
if=file
파일 이름 을 입력 하 십시오. 표준 입력 으로 부족 합 니 다.
of=file
출력 파일 이름, 표준 출력 이 부족 합 니 다.
ibs=bytes
bytes 바이트 (즉, 블록 크기 는 bytes 바이트) 를 한 번 에 읽 습 니 다.
obs=bytes
바이트
bs=bytes
읽 기와 쓰기 블록의 크기 를 bytes 로 설정 하여 ibs 와 obs 를 대체 할 수 있 습 니 다.
cbs=bytes
버퍼 를 바 꾸 는 bytes 바이트
크기
skip=blocks
입력 파일 의 시작 부분 에서 Blocks 블록 을 건 너 뛰 고 복 사 를 시작 합 니 다.
seek=blocks
출력 파일 의 시작 부분 에서 Blocks 블록 을 건 너 뛰 고 복 사 를 시작 합 니 다.(출력 파일 이 디스크 나 테이프 일 때 만 유효 합 니 다)
count=blocks
블록 블록 만 복사 합 니 다. 블록 크기 는 ibs 가 지정 한 바이트 수 와 같 습 니 다.
conv=conversion[,conversion...]
지정 한 매개 변수 로 파일 을 변환 합 니 다.
변환 매개 변수:
ascii 는 EBCDIC 를 ASCII 로 변환 합 니 다.
ebcdic 에서 ASCII 를 EBCDIC 로 변환 합 니 다.
ibm 에서 ASCII 를 alternate EBCDIC 로 변환 합 니 다.
block 은 각 줄 을 cbs 길이 의 기록 으로 바 꾸 고 부족 한 부분 은 빈 칸 으로 채 웁 니 다.
unblock
모든 줄 의 길 이 를 cbs 로 하고 부족 한 부분 은 빈 칸 으로 채 웁 니 다.
lcase 는 대문자 문 자 를 소문 자로 변환 합 니 다.
ucce 는 소문 자 를 대문자 로 변환 합 니 다.
swab 는 입력 한 바이트 한 쌍 을 교환 합 니 다.
noerror
오류 가 발생 했 을 때 멈 추 지 않 는 다.
notrunc
출력 파일 을 짧게 자 르 지 않 습 니 다.
sync 는 모든 입력 블록 을 ibs 바이트 에 채 우 고 부족 한 부분 은 빈 (NUL) 문자 로 보충 합 니 다.
dd 명령 은 바 이 너 리 방식 으로 읽 기와 쓰 기 를 허용 하기 때문에 원본 물리 장치 에서 입력 / 출력 하기에 특히 적합 합 니 다.예 를 들 어 다음 명령 으로 플 로 피 디스크 에 미 러 파일 을 만 들 수 있 습 니 다.
dd if=/dev/fd0 of=disk.img bs=1440k
재 미 있 는 것 은 이 미 러 파일 이 HD - Copy, Winimage 등 도구 소프트웨어 에 의 해
읽 어 내다.첫 번 째 하 드 디스크 의 앞 512 바이트 를 파일 로 저장 합 니 다.
dd if=/dev/hda of=disk.mbr bs=512 count=1
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.