http://muosys.egloos.com/l2

'리눅스커널 > Device Driver' 카테고리의 다른 글

[charger] bq2415x  (0) 2017.06.12
PS/2 키보드 LED제어  (0) 2015.05.13
문자디바이스 드라이버와 file_operations  (0) 2015.05.12
IOCTL  (0) 2015.05.12
디바이스드라이버기초정리  (0) 2015.05.11

학교에서 수업때 배운 내용이지만 다시봐도 새롭다.

쟈료를 가지고 따라가보겠다.

 

- PS/2 제어 레지스터

   PS/2 는 8042 라고 하는 컨트롤러가 제어한다. 이것음 다음과 같은 I/O주소를 갖는다.

 

PORT    READ/Write        Function

0x60        Read                Read Input Buffer

0x60        Write                Write Output Buffer

0x64        Read                Read Status Register

0x64        Write                Send Command

 

 

PS/2 키보드를 제어하기위해 컨트롤러에 명령을 써야 하는데 이때 사용하는 레지스터가 0x64번지 이다.

이번지에 명령을 쓴다. 즉 위의 Send Command 레지스터에 써 넣는다.

   - 0xEE : 에코 요청 명령

   - 0xED: 키보드에 있는  LED를 끄거나 키기 위한 명령

 

키보드에 읽을데이터가 있는가 확인할때는  0x64를 읽으면 된다.

PC 에서 키보드 데이터를 써 넣었다면 8042 입장에서는 input 이므로 비트 0번이 1이된다.

데이터를 써 넣기 전에 비트 0번이 1이 아닌가를 확인하고 써 넣어야 한다.

 

---키보드 응답 또는 전송 데이터 읽기

 

1) 0x64번지의 읽은 값의 비트1을 읽어 1이 될때까지 기다린다.

2) 0x60번지를 읽으면 키보드에서 전송한 데이터를 읽을 수 있다.

 

이때 0x64번지를 읽는 과정에서 문제가생겨 무한루프에 빠지지 않도록 다음과 같이 구현한다.

u8 ps2_key_read_data(void)

 

 

 

--명령 전송 및 응답 데이터 읽기

1) 0x64 번지에 명령을 써 넣는다.

2) 0x64 번지를 읽어 비트 0이 0이 될때까지 기다린다.

3) 0x64 번지를 읽어 비트 1이  1이 될때까지 기다린다.

   키보드가 명령을 받으면 응답데이터를 보내므로 이 값을 얻기위해서 이다.

4) 0x60 번지를 읽으면 키보드에 전송한 데이터를 읽을 수 있다.

 

 

 

 

LED를 키려변 1로 셋한다

0비트 : SCROLL LOCK

1비트 : NUM LOCK

2비트 : CAPS LOCK

 

 

if(0xFA != ps2_key_exchange_data(0x01)) return 0;

 

-버퍼 클리어

 

참고 : B004_다중 소스 모듈과 PS2키보드  - 유영창

'리눅스커널 > Device Driver' 카테고리의 다른 글

[charger] bq2415x  (0) 2017.06.12
USB 인사이드 muosys.egloos.com  (0) 2016.05.16
문자디바이스 드라이버와 file_operations  (0) 2015.05.12
IOCTL  (0) 2015.05.12
디바이스드라이버기초정리  (0) 2015.05.11

IT EXPERT 의 리눅스 디바이스 드라이버  -유영창 - 을 읽으며   정리해 보았다.

 

문자디바이스 드라이버의 특성 바이트 단위로 처리되고, 써넣는 데이터는 보존될 수도 , 보존되지 않을 수도 있다.

 

문자 디바이스 드라이버의 경우

 

char_dev.c

/usr/src/linux-4.0.2/include/linux/fs.h

 

/usr/src/linux-4.0.2/include/linux/types.h"

 

 

typedef long long   __kernel_loff_t;  // 8byte 32bit system

 #if defined(__GNUC__)
typedef __kernel_loff_t     loff_t;
#endif



 

 

 

 

struct module *owner;

- 파일 오퍼레이션의 소유자를 나타낸다. 디바이스 드라이버의 사용 횟수를 커널에서 관리해야 하기 때문에 이 필드를 지정한다. 보통은 THIS_MODULE을 지정한다.

ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);

- 디바이스 드라이버의 비동기 읽기를 구현하는 함수를 지정한다. 일반적인 디바이스 드라이버에서는 이 기능을 사용하지 않기 때문에 NULL을 지정한다.

 

문자디바이스 드라이버를 동작하려면 커널에 등록되어 있어야한다.

<linux/fs.h> 헤더파일을 소스에 포함 시켜야 한다.

- register_chrdev : 디바이스를 등록한다.

- unregister_chrdev:등록된 디바이스를 제거한다.

 

 

/usr/src/linux-4.0.2/include/linux/fs.h"

 

 

 

 

 

'리눅스커널 > Device Driver' 카테고리의 다른 글

USB 인사이드 muosys.egloos.com  (0) 2016.05.16
PS/2 키보드 LED제어  (0) 2015.05.13
IOCTL  (0) 2015.05.12
디바이스드라이버기초정리  (0) 2015.05.11
platform_driver  (0) 2015.04.23

아직멀었구나..

 

괜히 최신커널쓴다고 오류만 난발.

오늘도 에러가..

문자 디바이스 드라이버 구조체중에 ioctl()함수가 사라지고 이두개를 사용한다고 한다.

 

.unlocked_ioctl or .compat_ioctl 사용!

 세부정보 : http://forum.falinux.com/zbxe/?document_srl=563022 FF포럼

 

long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);

long (*compat_ioctl) (struct file *, unsigned int, unsigned long);

 

인자만 한개 지워주니깐 성공. 휴.

세부사항은 검색 하십쇼!

 

디바이스 예제. //ioctl.c

#include <linux/init.h>

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/fs.h>

 

int kw_device_open(struct inode *inode, struct file *filp)

{

       printk(KERN_ALERT "kw_device open fuction called\n");

       return 0;

}

 

int kw_device_release(struct inode *inode, struct file *filp)

{

       printk(KERN_ALERT "kw_device release fuction called\n");

       return 0;

}

 

//ioctl 연산 구현 부분 기존 read, write연산 제거하고 모두 ioctl 구현

int kw_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

//변형

{

       switch(cmd)

       {

       case 1: //read

             printk(KERN_ALERT "ioctl read...\n");

             break;

       case 2: //write

             printk(KERN_ALERT "ioctl write...\n");

             break;

            

       default:

             printk(KERN_ALERT "ioctl unknown command...\n");

             break;

       }

       return 0;

}

 

//동작만 살펴보기 위해 간단한 메세지만 출력하 였다.

 

static struct file_operations vd_fops ={

             .owner        = THIS_MODULE,

             .open         = kw_device_open,

             .release     = kw_device_release,

             .unlocked_ioctl     = kw_device_ioctl  //변형부분!

};

 

int __init kw_device_init(void){

       // 문자 디바이스를 등록한다.

       if(register_chrdev(250,"kw_device", &vd_fops) <0 )

             printk(KERN_ALERT "driver init failed\n");

       else

             printk(KERN_ALERT "driver init successful\n");

       return 0;

}

 

void __exit kw_device_exit(void){

       unregister_chrdev(250,"kw_device");

       printk(KERN_ALERT "driver cleanup successful!\n");

}

 

module_init(kw_device_init);

module_exit(kw_device_exit);

MODULE_LICENSE("GPL");

 

응용프로그램 //ioctl_app

 

파일 첨부..

 

ioctl.zip

                       책: 리눅스 커널 프로그래밍(한빛) 에서

                             소스작성중.

'리눅스커널 > Device Driver' 카테고리의 다른 글

USB 인사이드 muosys.egloos.com  (0) 2016.05.16
PS/2 키보드 LED제어  (0) 2015.05.13
문자디바이스 드라이버와 file_operations  (0) 2015.05.12
디바이스드라이버기초정리  (0) 2015.05.11
platform_driver  (0) 2015.04.23

 

리눅스버전 3.19.4

 

 

커널에 자원 처리를 요청하는 방법은 시스템 호출    과 파일입출력을 이용하여 드바이스 드라이버를 사용하는 방식

 

 

 

 

/usr/src/linux-3.19.4/include/linux/types.h 의

15 typedef __kernel_dev_t      dev_t;

 12 typedef __u32 __kernel_dev_t;

 

진입점 (entry point, entrance)  IT용어사전, 한국정보통신기술협회

진입점 [entry point, entrance, 進入點] (용어해설)

 1. 어떤 프로그램이나 서브루틴의 시작주소. 즉 제어를 서브루틴으로 옮기기 위해 분기하는 주소이다.

 2. 어떤 서브루틴을 호출 했을 때 그 안에서 제일 먼저 실행되는 명령어

 

 

  • 커널에 모듈 삽입/제거 명령어
      Insmod
    sys_create_module(모듈을 위한 메모리 공간 할당 받음)
    get_kernel_syms(모듈 링크위한 커널 심볼테이블 작업)
    sys_init_module(코드 복사, 모듈의 초기화함수 호출)
  •  rmmod는 내부적으로
    delete_module 호출 → 사용수 카운트가 0 이면
    cleanup_module 호출

/usr/src/linux-3.19.4/Documentation$ vim devices.txt
linux-3.19.4/include/uapi/linux/major.h   에 디바이스에대한 major 즉 주번호 들이 정의되어 있다.

 

실제 사용중인 주번호는 "cat /proc/devices" 를 통해서 확인 가능

root@li:/usr/src/linux-3.19.4/include/uapi/linux# cat /proc/devices
Character devices:
  1 mem        4 /dev/vc/0        4 tty         4 ttyS         5 /dev/tty     5 /dev/console
  5 /dev/ptmx   5 ttyprintk         6 lp         7 vcs         10 misc        13 input
 14 sound/midi   14 sound/dmmidi          21 sg          29 fb            99 ppdev
108 ppp             116 alsa                       128 ptm      136 pts          180 usb
189 usb_device   216 rfcomm                  226 drm       251 hidraw     252 bsg
253 watchdog     254 rtc

 

Block devices:
  1 ramdisk    2 fd       259 blkext       7 loop
  8 sd           9 md11 sr
 65 sd   66 sd 67 sd   68 sd     69 sd   70 sd   71 sd  128 sd           129 sd
130 sd  131 sd   132 sd  133 sd  134 sd
135 sd      252 device-mapper   253 virtblk  254 mdp
 

 

 

 

 

 

참고

 리눅스 디바이스 드라이버-유영창

 심볼 테이블  http://kirari83.tistory.com/entry/EXPORTSYMBOL

 플랫폼디바이스 드라이버 http://blog.naver.com/sigsaly/100102042663

 

 

 

'리눅스커널 > Device Driver' 카테고리의 다른 글

USB 인사이드 muosys.egloos.com  (0) 2016.05.16
PS/2 키보드 LED제어  (0) 2015.05.13
문자디바이스 드라이버와 file_operations  (0) 2015.05.12
IOCTL  (0) 2015.05.12
platform_driver  (0) 2015.04.23

PNP 기능을 플랫폼 드라이버라는 형태로 지원한다.

 

드라이버의 기본동작을 구현하기 위한 자료구조체

/usr/src/linux-3.19.4/include/linux/platform_device.h

 

174 struct platform_driver {
175     int (*probe)(struct platform_device *);
176     int (*remove)(struct platform_device *);
177     void (*shutdown)(struct platform_device *);
178     int (*suspend)(struct platform_device *, pm_message_t state);
179     int (*resume)(struct platform_device *);
180     struct device_driver driver;
181     const struct platform_device_id *id_table;
182     bool prevent_deferred_probe;
183 };

 

490 #define PLATFORM_NAME_SIZE  20
491 #define PLATFORM_MODULE_PREFIX  "platform:"
492    
493 struct platform_device_id {
494     char name[PLATFORM_NAME_SIZE];
495     kernel_ulong_t driver_data;
496 };  

 

 

보통 사용 예

 static struct platform_driver test_driver=

{

  .probe = test_probe,

  .remove= test_remove,

  .suspend= test_suspend

  .resume = test_resume,

  .driver ={

              .name = TEST_DEVICE_DRIVER_NAME,

  },

};

 

 

  • probe() 디바이스가 추가 되었을 때 처리하는 함수를 지정
  • remove() 디바이스가 제거 되었을 때 처리하는 함수를 지정
  • shutdown() 디바이스의 동작을 중지 시킬때 처리하는 함수
  • resume() 디바이스의 동작을 재시작 시킬 때 처리하는 함수
  • driver 구조체 내부의 name 필드만 보통 지정, 나머지 필드는 커널 내부에서 관리되면서 채워진다.
  • id_table  probe()함수가 호출되는 과정에서 해당 디바이스를 구별하고 처리하기 위한 내부 데이터를 지정하는 목적

 

 

 

플랫폼 드라이버 구조체 정보는 다음과 같은 함수로 커널에 등록되거나 제거된다.

  • int platform_driver_register(struct platform_driver *pdev);
  • void platform_dirver_unregister(struct platform_driver *pdev);

 

    platform_driver_register() 함수는  : pdev 정보를 커널 내부에 등록하기 위해서 사용되므로 보통 모듈 초기화 함수에서 사용된다. 반환값이 0이면 정상이다.

 


188 /*
189  * use a macro to avoid include chaining to get THIS_MODULE
190  */
191 #define platform_driver_register(drv) \
192     __platform_driver_register(drv, THIS_MODULE)
193 extern int __platform_driver_register(struct platform_driver *,
194                     struct module *);
195 extern void platform_driver_unregister(struct platform_driver *); 

 

 32 #ifdef MODULE
 33 extern struct module __this_module;
 34 #define THIS_MODULE (&__this_module)
 35 #else
 36 #define THIS_MODULE ((struct module *)0)
 37 #endif

 

다른버전 ----4.0.2

/usr/src/linux-4.0.2/drivers/base/platform.c

 

 

 

 

 

 

 

 

참조 : B003_디바이스 드라이버 모듈 (유영창)

 

 

 

'리눅스커널 > Device Driver' 카테고리의 다른 글

USB 인사이드 muosys.egloos.com  (0) 2016.05.16
PS/2 키보드 LED제어  (0) 2015.05.13
문자디바이스 드라이버와 file_operations  (0) 2015.05.12
IOCTL  (0) 2015.05.12
디바이스드라이버기초정리  (0) 2015.05.11

리눅스 커널 컴파일을 해보자 .

테스트사양 ubuntu-14.04.2  메모리 2GB 프로세스2개

 

커널을 받기위해 사이트를 접속한다.

https://www.kernel.org/하트3

 

 

 

커널 소스는 보통 /usr/src 폴더에 보관한다?

받은 소스를 /usr/src폴더에 옮긴후 다운받은 압축파일을 풀어헤친다

 

터미널 창에서 root@li:/usr/src# tar xvf linux-3.19.4.tar.xz 

압축을 풀고 cd linux-3.19.4

 

1. apt-get install ncurses-dev   (필요한 패키지를 설치한다.)

커널 컴파일하기전에 /boot/config-3.16.0-30-generic   커널 설정파일을 .config파일로 옮긴다.

cp config-3.16.0-30-generic /usr/src/linux-3.19.4/.config

2. make menuconfig   (커널 관련 설정파일을 설정하는 부분)

 

 

 

Load (선택) 방금복사한 파일 .config (OK) Save 세이브한다.

통합 커널 컴파일 할수있는 툴을 설치한다.

추가 apt-get update

3. apt-get install kernel-package

4. make-kpkg -j8 --initrd --revision=1.0 kernel_image  

    (revision= 버전)생성될 파일의 버전을 의미한다. -j 옵션 프로세스 *2(멀티컴파일? CPU를 여러개사용하여 컴파일 빠르도록)

    현재시각 16시 29분 ( 프로세스가 4개이므로 *2인 옵션에 8)

 결과사진

 

상위폴더에 cd ../

linux-image-3.19.4_1.0_amd64.deb  파일이 생성 되었는지 확인

 

 

5.   dpkg -i linux-image-3.19.4_1.0_amd64.deb

/boot 및 /lib/modules 에 파일이 추가된다 

 

6.  reboot now

 

7.  uname -a  (커널 버전이 바뀌었는지 확인한다.

 


 

과거 컴파일시

 

 

 

make -j8

아키텍쳐 부트 폴더의 bzImage 를 boot에 vmlinux-XXX로 복사

update-initramfs -c -k 2.6.29

Sudo update-grub

 

 

이상 쉬엇!

 

 


 

 

 

 

'리눅스커널' 카테고리의 다른 글

LCD (1)  (1) 2016.06.23
ARM 리눅스 커널 3.0 포팅(Porting the Linux kernel 3.0 for ARM Architecture)  (0) 2016.06.23
시스템콜  (0) 2015.04.16
systemcall  (0) 2015.04.15
스와퍼(Swapper)프로세스  (0) 2015.04.15

 

 

시스템 콜은 응용프로그램에서 운영체제에게 어떠한기능(시스템 자원)을 수행해 달라고 하는 하나의 수단이다.

- 저수준 프로그래밍을 몰라도 프로그래밍 가능, 프로그램 호환성이 좋다.

- 사용자 요청을 처리하기전에 인터페이스 수준에서 올바른 요청인지 검사할 수 있으므로 시스템 보완성이 높다.

 

 

 

시스템 콜의 종류 - type 별로 구분

  - 프로세스 제어

  - 파일조작

  - 장치 관리

  - 시스템 정보 및 자원 관리

  - 통신관련

  - 시스템콜의 초기화는 시스템 부팅시 커널 초기화 과정에서 trap_init()함수 내의 set_system_gate(SYSCALL_VECTOR, &system_call)을

     수행해서 0x80 인터럽트를 위한 게이트 디스크립터를 설정

  • SYSCALL_VECTOR : 0x80로 정의된 상수
  • &system_call : 시스템 콜을 위한 핸들러주소

 메모리 주소 영역이 커널 주소영역사용자 주소영역 으로 구분되어있기 때문에, 사용자 프로세스에서 커널 영역에

 접근시 Segmentation Fault 메시지를 출력하면서 프로세스가 종료된다. (커널 스레드나 디바이스드라이버 계층만 접근가능) 

 

arm 은 SWI 명령을 사용하면 내부 인터럽트가 발생한다.

x86에서는 eax에 시스템 콜 번호를 넣고 0x80번 인터럽트를 발생시킨다.

 

ARM의 경우

 -- USER 모드의 태스트에서 SWI 명령을 사용해서 특권모드인 SVC 모드로 진입하고, SWI 핸들러는 SWI 명령의 인자로 넘어오는 시스템 콜 번호를 보고서 어떻게 동작할지 결정한다.

 

 

 

 그림[1] 시스템 콜

 

 

 

[그림2] 시스템 콜 함수 찾아가는 과정

 

음.. fork()함수를 썻을때 glibc라이브러리를 통해 vfork()로 연결되는 부분을 찾고싶은데????????........어떻게하지

일단 라이브러리 소스를 받아보았다.. 졸려...............퓨ㅜ

 

 

 

[그림3] ARM 에서의 시스템콜  호출순서를 보자

   1.  사용자 프로세스에서 fork를 호출

   2.  glibc에 래핑되어 있는 fork함수가 호출되어 vfork함수를 호출한다. swi __NR_vfork 명령으로 시스템 콜을 호출하면  

   3. exception vector table로 들어간다(커널영역)

       (fork()의 시스템 콜 번호가 0x02 므로 여기에 4를 곱해 ,해당 시스템 콜을 처리하는 함수의 주소가

       System Call Vector Table의 어느 위치에 있는지 계산)

   4. sys_fork() 함수로 분기

 

 glibc - GNU C library 의 약자. GNU 시스템과 Linux에서 사용되는 대표적인 C라이브러리

glibc받기

http://www.gnu.org/software/libc/

 

 

 

 

참고

 - 12장 시스템 콜 구현하기(도전 임베디드 OS만들기 [이만우])

 - 휴인스 쟈료   www.huins.com

 - 리눅스 커널기초 http://idkkangjs.blog.me/30091117058

 - ARM 아키텍쳐   http://www.jkelec.co.kr/img/lecture/arm_arch/arm_arch_3.html

 - FALinux Forum [커널산책]

http://forum.falinux.com/zbxe/index.php?document_srl=575411

 

'리눅스커널' 카테고리의 다른 글

ARM 리눅스 커널 3.0 포팅(Porting the Linux kernel 3.0 for ARM Architecture)  (0) 2016.06.23
커널컴파일  (0) 2015.04.17
systemcall  (0) 2015.04.15
스와퍼(Swapper)프로세스  (0) 2015.04.15
schedule()함수  (0) 2015.04.15

http://kernelnewbies.org/FAQ/DoWhile0

 

 

그외참고 튜닝? http://jh4hj.tistory.com/entry/%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%94%94%EB%B2%84%EA%B9%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%B9%9C%EA%B5%AC

 

스템콜 추가

 

asmlinkage : 어셈블리 언어로 구현된 함수에서 호출될 때 사용하는 keyword

 

 

arch/x86/kernel/syscall_table_32.S

최신커널 : /arch/x86/syscalls/syscall_*.tbl

   1 ENTRY(sys_call_table)
  2     .long sys_restart_syscall   /* 0 - old "setup()" system call, used for restarting */
  3     .long sys_exit
  4     .long ptregs_fork
192     .long ptregs_vfork  /* 190 */

339     .long sys_bit               /* 337 */   //새로 추가

 

어셈블러 지시자들 (자세한 내용은 아래 asm 링크 참고)

 

 

 

 

 

 

 

/usr/src/linux-2.6.32.65/arch/x86/include/asm/unistd_64.h

최근 /arch/x86/syscalls/syscall_*tbl

 134 #define __NR_clone              56
135 __SYSCALL(__NR_clone, stub_clone)
136 #define __NR_fork               57
137 __SYSCALL(__NR_fork, stub_fork)
138 #define __NR_vfork              58
139 __SYSCALL(__NR_vfork, stub_vfork)
#define __NR_perf_event_open            298

 

664 #define __NR_bit                        299
665 __SYSCALL(__NR_bit, sys_bit)

 

#define NR_syscalls (__NR_syscall_max + 1)   --> 따라가서 변경

///usr/src/linux-2.6.32.65/include/asm/asm-offsets.h

 

ARM

/usr/src/linux-2.6.32.65/arch/arm/include/asm/unistd.h

 시스템 콜 번호를 정의한다.

 

 

 

/usr/src/linux-2.6.32.65/include/linux/syscalls.h

kernel 에 소스추가 및 Makefile 에 파일 추가

작성 후 Makefile 에 소스 추가 및 재 컴파일 한다.

 

 

함수추가는 : /include/linux/syscalls.h

 

어플리케이션에서 시스템 콜 호출

 

 

--------------------------------------------------------------------

신규버전

 

 

 

 

참고

asm   : http://korea.gnu.org/manual/release/as/as-ko_7.html

KLDP : http://kldp.org/node/91565

http://harryp.tistory.com/69

 http://harryp.tistory.com/69

linux system call 의 호출 구조   http://www.hanbit.co.kr/network/view.html?bi_id=1062  저자 : 서민우     출처: Embedded World

 


 

'리눅스커널' 카테고리의 다른 글

커널컴파일  (0) 2015.04.17
시스템콜  (0) 2015.04.16
스와퍼(Swapper)프로세스  (0) 2015.04.15
schedule()함수  (0) 2015.04.15
프로세스1-3  (0) 2015.04.14

+ Recent posts