41日目-車両オペレーティングシステム

81854 ワード

ロールデバイス

  • file.koモジュールファイルがカーネル内部にアップロードされます.
  • アップグレードされたモジュールは、必要に応じてカーネルを介して呼び出されます.
  • コンテキストの切り替え


  • CPU
  • Register Context.
  • stack:私のパーソナルスペース(プログラムが自分で使うスペース)
  • User Context
  • OSは多くのプロセスを処理するのが難しい.
  • Task Control Block->同じ服を着ます.(番号)
  • この情報を使用して、どのプロセスが何をしているか、何をしているかを識別します.
  • ProcessIdは多くのプログラムを制御する.
  • System Context.(オペレーティングシステムが動作するスペース)
  • 実行中のプロセスを一時停止します(より重要なタスクがある場合は優先度が高くなります).
    CPUのRegiter値をスタックに配置し、OSのTask Control Blockメモリに格納します.
  • 一時冷凍と同様である.(交換が多くてもプログラムには影響しない.->結果は同じ)
  • 必要に応じて、これらの値は再びロードされます.
  • void * OSTaskStkInit(void (*task)(void *pd), void *pdata, void *ptos, INT16U opt)
    {
    	OS_STK*	stk;
    
    	stk = (OS_STK *) ptos;			// Load stack pointer
    
    	*--stk = (INT32U) pdata;			// Simulate a function call (to pass the parameter)
    	*--stk = (INT32U) TaskBucket;	// Return address in case the task exits.
    
    	*--stk = 0x00000202;			// Eflags (interrupt flag enabled)
    	*--stk = CS_SELECTOR;			// CS
    	*--stk = (INT32U) task;			// Entry point
    
    	*--stk = 0;						// EAX
    	*--stk = 0;						// ECX
    	*--stk = 0;						// EDX
    	*--stk = 0;						// EBX
    	*--stk = 0;						// ESP (unused)
    	*--stk = 0;						// EBP
    	*--stk = 0;						// ESI
    	*--stk = 0;						// EDI
    
        return stk;
    }
  • オペレーティングシステムでのプログラミング切り替えContext
  • 実習スケルトンの作成

    /***************************************
     * Filename: sk.c
     * Title: Skeleton Device
     * Desc: module_init, module_exit
     ***************************************/
    #include <linux/module.h>
    #include <linux/init.h>
    
    MODULE_LICENSE("GPL");
    
    static int sk_init(void)
    {
        printk("SK Module is up... \n");
        return 0;
    }
    
    static void sk_exit(void)
    {
        printk("The module is down...\n");
    }
    
    module_init(sk_init);  
    module_exit(sk_exit);  
  • sk.c合成
  • obj-m += sk.o  #startstop.o#hello-1.o hello-2.o hello-3.o hello-4.o
    startstop-objs := start.o stop.o
    
    #KDIR   := /lib/modules/$(shell uname -r)/build
    KDIR    := /tftpboot/kernel-mds2450-3.0.22
     
    all:
        make -C $(KDIR) SUBDIRS=$(PWD) modules
    
    clean:
        make -C $(KDIR) SUBDIRS=$(PWD) clean
  • make file作成後make
  • insmod、lsmodおよびrmmod挙動検査
  • ロールデバイスの登録

  • 提供されたAPIを使用して符号化する必要がある.
  • ポインタ配列と配列ポインタ

  • デバイスドライバは、この操作を実行する上で非常に重要です.
  • 포인터 배열 및 배열 포인터 활용사례
    
    1. main 함수 argv : 명령어 라인 인풋
    
    2. 드라이버 등록 함수 -> register_chardev
    
    3. 시그날 함수 -> signal
      - 응용프로그램이 상황을 인지할 때 (OS 빼고는 알 수가 없으므로.. 북한)
    
    4. 문자열 간접 정렬 - DataBase index 정렬.. 
    
    5. 인터럽트 핸들링(벡터링) - 펌웨어 c_handler 함수
    
    6. 동적 배열 활용 - dynamic array
    
    7. 기타 교재내의 예제들 etc ...
  • major numberでは、デバイスの名前、実行中の関数のアドレスを知ることができますので、file operationsを使用できます.
  • API

  • 関数名が変更されました.
    regstister chrdev P:登録文字デバイス
    unregister chrdev:文字デバイスの無効化
    =========>>以前の方法
    cdev_init, cdev_add... register_chrdev_region.. 等
  • register_chrdev_region()

  • カウント値を持つデバイスドライバの登録
  • int allokc_chrdev_regino(dev_t first, unsigned int count, char* name)
  • alloc_chrdev_region()

  • 動的割当てデバイス番号の関数
  • int alloc_chrdev_region(dev_t dev, unsinged int firstminor, unsinged int count, char name)
  • *dev:成功時割当機器番号
  • firstmino:デバイスに割り当てられた最初のminor番号.通常は0
  • count:デバイス番号はマイナー番号
  • *name:デバイス名(/proc/devicesおよびsysfsに表示)
  • Manual allcoation


    Dynamic allocation

  • alloc chrdev region()関数動的割当て
  • デバイスファイルを事前に作成することはできません.
  • デバイス番号を登録し、/proc/devicesを読み込んで編集長番号を取得し、スクリプトを使用してデバイスFire
  • を作成します.

    Major/Minor Number組合せ

  • Major(12bits), Monor(20bits)
  • cdev構造体

    struct cdev
    {
        struct kobject kobj;
        struct module *owner;
        const struct file_operations *pos;
        struct list_head list;
        dev_t dev;
        unsigned int count;
    }
  • linux/cdev.hに含める
  • cdev構造を用いて内部ロールデバイスを表す
  • すべてのドライバにkobjがあります.
  • file operation:open,readなどの実際のモバイルデバイスの関数
  • cdev init()ロールデバイスの登録


    cdev add()ロールデバイスの登録


    cdev del()ロールデバイスを無効にする


    実習デバイス登録

    /***************************************
       * Filename: sk.c
       * Title: Skeleton Device
       * Desc: register and unregister chrdev
    ***************************************/
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/fs.h> // 파일에 읽고 써야하니까
    #include <linux/cdev.h> // 캐릭터 디바이스 (저장매체들)
    
    MODULE_LICENSE("GPL");
    
    static int sk_major = 0, sk_minor = 0;
    static int result;
    static dev_t sk_dev;
    /* file_operations의 레코드를 할당한다. */
    static struct file_operations sk_fops;
    static struct cdev sk_cdev;
    
    static int sk_register_cdev(void);
    
    static int sk_init(void)
    {
    	printk("SK Module is up... \n");
    	/* 문자 디바이스의 등록 */
    	if((result = sk_register_cdev()) < 0)
    	{
    		return result;
    	}
    	return 0;
    }
    
    static void sk_exit(void)
    {
    	printk("The module is down...\n");
    
    	cdev_del(&sk_cdev); // 장치 떼어낸다.
    	unregister_chrdev_region(sk_dev, 1); // 번호 해제
    }
    
    static int sk_register_cdev(void)
    {
    	int error;
    
    	/* allocation device number */
    	if(sk_major) 
    	{
    		sk_dev = MKDEV(sk_major, sk_minor);
    		error = register_chrdev_region(sk_dev, 1, "sk");
    	} else 
    	{
    		error = alloc_chrdev_region(&sk_dev, sk_minor, 1, "sk");
    		sk_major = MAJOR(sk_dev);
    	}
    
    	if(error < 0) 
    	{
    		printk(KERN_WARNING "sk: can't get major %d\n", sk_major);
    		return result;
    	}
    
    
    	printk("major number=%d\n", sk_major);
    
    	/* register chrdev */
    	cdev_init(&sk_cdev, &sk_fops);
    	sk_cdev.owner = THIS_MODULE;
    	sk_cdev.ops = &sk_fops;
    	error = cdev_add(&sk_cdev, sk_dev, 1);
    
    	if(error)
    		printk(KERN_NOTICE "sk Register Error %d\n", error);
    
    	return 0;
    }
    
    module_init(sk_init); 
    module_exit(sk_exit);

    実習デバイスファイルの作成

    lsmod sk2.ko
    mknod /dev/SK c 253 0 # device name, type, major number, minor nubmber
    ls /dev -al | grep SK
    rm /dev/SK
    rmmod sk

    file_operations

  • この構造体は、関数ポインタセットです.
  • int (ioctl) (struct inode , struct file *, unsinged int, unsinged long);
  • H/Wハプニング機能の関数重要
  • loff_t (llseek) (struct file , loff_t, int)
  • 必要な読み書き位置に移動する関数
  • int (*open)
  • ファイルを開きますが、誰かが開いている場合は開きません.
  • 実習open & release

    
    
    
    
    /***************************************
       * Filename: sk.c
        * Title: Skeleton Device
    	 * Desc: Implementation of system call
    	  ***************************************/
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/major.h>
    #include <linux/fs.h>
    #include <linux/cdev.h>
    
    MODULE_LICENSE("GPL");
    
    static int sk_major = 0, sk_minor = 0;
    static int result;
    static dev_t sk_dev;
    
    static struct cdev sk_cdev;
    
    static int sk_register_cdev(void);
    
    /* TODO: Define Prototype of functions */
    static int sk_open(struct inode *inode, struct file *filp);
    static int sk_release(struct inode *inode, struct file *filp);
    
    /* TODO: Implementation of functions */
    static int sk_open(struct inode *inode, struct file *filp)
    {
    	printk("Device has been opened...\n");
    		 
    	/* H/W Initalization */
    		    
    	//MOD_INC_USE_COUNT;  /* for kernel 2.4 */	    
    	return 0;
    }
    
    static int sk_release(struct inode *inode, struct file *filp)
    {
    	printk("Device has been closed...\n");
    	return 0;
    }
    
    struct file_operations sk_fops = { 
    	.open       = sk_open,
    	.release    = sk_release,
    };
    
    static int __init sk_init(void)
    {
    	printk("SK Module is up... \n");
    
    	if((result = sk_register_cdev()) < 0)
    	{
    		return result;
    	}
        return 0;
    }
    
    static void __exit sk_exit(void)
    {
    	printk("The module is down...\n");
    	cdev_del(&sk_cdev);
    	unregister_chrdev_region(sk_dev, 1);
    }
    
    static int sk_register_cdev(void)
    {
    	int error;
    
    	/* allocation device number */
    	if(sk_major) 
    	{
    		sk_dev = MKDEV(sk_major, sk_minor);
    		error = register_chrdev_region(sk_dev, 1, "sk");
    	} 
    	else 
    	{
    		error = alloc_chrdev_region(&sk_dev, sk_minor, 1, "sk");
    		sk_major = MAJOR(sk_dev);
    	}
    
    	if(error < 0) 
    	{
    		printk(KERN_WARNING "sk: can't get major %d\n", sk_major);
    		return result;
    	}
    	printk("major number=%d\n", sk_major);
    
    
    	/* register chrdev */
    	cdev_init(&sk_cdev, &sk_fops);
    	sk_cdev.owner = THIS_MODULE;
    	sk_cdev.ops = &sk_fops;
    	error = cdev_add(&sk_cdev, sk_dev, 1);
    
    	if(error)
    		printk(KERN_NOTICE "sk Register Error %d\n", error);
    
    	return 0;
    }
    
    module_init(sk_init); 
    module_exit(sk_exit);
  • openの実行順序
  • open->library->S/W Interrupt(オペレーティングシステム呼び出し:やってください.これはアプリケーションソフトウェアではできません)->システム呼び出し->VFS(仮想ファイルシステム、/dev/sk)->CHR.Device File -> Device Driver
  • Openはファイル名しか知らない->システム呼び出し、VFSに移動し、Major NumberとFileのタイプを見つけ、モバイルハードウェアの関数を見つけます.
  • 実習writeの追加

    /***************************************
    * Filename: sk.c
    * Title: Skeleton Device
    * Desc: Implementation of system call
    ***************************************/
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/major.h>
    #include <linux/fs.h>
    #include <linux/cdev.h>
    #include <asm/uaccess.h>
    
    MODULE_LICENSE("GPL");
    
    static int sk_major = 0, sk_minor = 0;
    static int result;
    static dev_t sk_dev;
    
    static struct cdev sk_cdev;
    
    static int sk_register_cdev(void);
    
    /* TODO: Define Prototype of functions */
    static int sk_open(struct inode *inode, struct file *filp);
    static int sk_release(struct inode *inode, struct file *filp);
    static int sk_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos);
    
    /* TODO: Implementation of functions */
    static int sk_open(struct inode *inode, struct file *filp)
    {
    	printk("Device has been opened...\n");
    		    
    	/* H/W Initalization */
    		    
    	return 0;
    }
    
    static int sk_release(struct inode *inode, struct file *filp)
    {
    	printk("Device has been closed...\n");
    	return 0;
    }
    
    static int sk_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
    {
    	char data[11];
    
    	copy_from_user(data, buf, count);
    	printk("data >>>>> = %s\n", data);
    
    	return count;
    }
    
    struct file_operations sk_fops = { 
    	.open       = sk_open,
    	.release    = sk_release,
    	.write      = sk_write,
    };
    
    static int __init sk_init(void)
    {
    	printk("SK Module is up... \n");
    
    	if((result = sk_register_cdev()) < 0)
    	{
    		return result;
    	}
    
    	return 0;
    }
    
    static void __exit sk_exit(void)
    {
    	printk("The module is down...\n");
    	cdev_del(&sk_cdev);
    	unregister_chrdev_region(sk_dev, 1);
    }
    
    static int sk_register_cdev(void)
    {
    	int error;
    
    	/* allocation device number */
    	if(sk_major) 
    	{
    		sk_dev = MKDEV(sk_major, sk_minor);
    		error = register_chrdev_region(sk_dev, 1, "sk");
    	} else {
    	error = alloc_chrdev_region(&sk_dev, sk_minor, 1, "sk");
    	sk_major = MAJOR(sk_dev);
    	
    	if(error < 0) 
    	{
        		printk(KERN_WARNING "sk: can't get major %d\n", sk_major);
    		return result;
    	}
    	printk("major number=%d\n", sk_major);
    
    	/* register chrdev */
    	cdev_init(&sk_cdev, &sk_fops);
    	sk_cdev.owner = THIS_MODULE;
    	sk_cdev.ops = &sk_fops;
    	error = cdev_add(&sk_cdev, sk_dev, 1);
    
    	if(error)
    		printk(KERN_NOTICE "sk Register Error %d\n", error);
    
    	return 0;
    }
    
    module_init(sk_init); 
    module_exit(sk_exit);
  • sk4.c
  • /***************************************
    * Filename: sk_app.c
    * Title: Skeleton Device Application
    * Desc: Implementation of system call
    ***************************************/
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <fcntl.h>
    
    int main(void)
    {
    	int retn;
    	int fd;
    	/* write에서 사용할 버퍼 */
    	char buf[100] = "write...\n";
    				    
    	fd = open("/dev/SK", O_RDWR);
    	printf("fd = %d\n", fd);
    						    
    	if (fd<0) 
    	{
    		perror("/dev/SK error");
    		exit(-1);
    	}
    	else
    	printf("SK has been detected...\n");
    								    
    	/* fd가 가르키는 파일에 buf에 있는 10바이트를 쓰라는 의미 */
    	retn = write(fd, buf, 10);
    	printf("\nSize of written data : %d\n", retn);
    	close(fd);
    	
    	return 0;
    }
  • sk4_app.c
  • sk 4 makeおよびapp crosscompileの後、terterterm上でapp
  • を実行
    ./sk4

    甲級Linux同期

    A task -> -1 -> 1
    ↓
    Some Register -> 1 (A의 1 저장)
    ↑
    B task -> -1 -> 0 (B의 0 저장?)
  • 上記問題を阻止する方法Lock
  • 保存部でロックされ、最終的にチェックされます.
  • 保存するレジスタ値と同じ値を入力した場合は、最後にYes
  • を確認します.
  • 最終チェックNo?->ロールバックを再起動
  • Dead Lock
  • XレジストラAが値を変更し、YレジストラBが値Yを変更した場合、Xレジストラが値を変更しますか?->最後の検査でNoが出てきて何もできなかったので二人とも止めましたA-Bシステムは拡張中です.
  • 両方持っていくか、両方持っていけないか
  • アプリケーションが非常に多い場合、Loopを作成するにはDead Lockが必要です.
  • 未解決のジョブ
  • 綿密に設計された開発(オペレーティングシステムはすべての問題を解決することができず、開発者も努力しなければならない)
  • 解決策


  • 10種類.
  • Atomic operations
  • 上記の1つのソリューションが既に入手されている場合、別のソリューションは動作を停止する
  • 通常はハードウェア構成です.
  • Spin Locks
  • CPU間でもH/Wの競合がある.
  • 終了待ちを続ける.
  • 何かをすばやく処理するために使用されます.
  • Reader-Writer Semaphores
  • Updateの関数整数
  • RO,RW間の最大統合
  • ROファイルに同期の問題はありませんが、同時書き込みの問題があります.
  • プログラムの実行効率を向上させるために、最大書き込みファイルを削減しようとします.
  • Semaphores
  • H/W使用の権利.キーコンセプト
  • Semaphoresは変数を生成します.0:不可能、1:アクセス可能
  • Mutexes
  • Light Weight Semaphores
  • これは同時に実行できない概念であるため、プログラムの処理速度はより速い.
  • Barriers
  • Compiler->並べ替えの実行順序を変更します.
  • 変更後は問題なく、より高速なコード命令の順序が変更されます.
  • コードをロックおよび解放することができる.
  • このようなことを防止するために、ロックされた部分と解除された部分の壁が作成される.
  • 実習readの追加

    /***************************************
       * Filename: sk.c
        * Title: Skeleton Device
    	 * Desc: Implementation of system call
    	  ***************************************/
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/major.h>
    #include <linux/fs.h>
    #include <linux/cdev.h>
    #include <asm/uaccess.h>
    MODULE_LICENSE("GPL");
    static int sk_major = 0, sk_minor = 0;
    static int result;
    static dev_t sk_dev;
    static struct cdev sk_cdev;
    static int sk_register_cdev(void);
    /* TODO: Define Prototype of functions */
    static int sk_open(struct inode *inode, struct file *filp);
    static int sk_release(struct inode *inode, struct file *filp);
    static int sk_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos);
    static int sk_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
    /* TODO: Implementation of functions */
    static int sk_open(struct inode *inode, struct file *filp) {
    	printk("Device has been opened...\n");
    	/* H/W Initalization */
    	return 0;
    }
    static int sk_release(struct inode *inode, struct file *filp) {
    	printk("Device has been closed...\n");
    	return 0;
    }
    static int sk_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos) {
    	char data[11];
    	copy_from_user(data, buf, count);
    	printk("data >>>>> = %s\n", data);
    	return count;
    }
    static int sk_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) {
    	/* App. 에 전달할 문자열을 담은공간 */
    	char data[20] = "this is read func...";
    	/* App. 으로 전달 받은 주소로부터 count까지의 내용을 buf로 옮긴다 */
    	copy_to_user(buf, data, count);
    	return 0;
    }
    struct file_operations sk_fops = {
    	.open       = sk_open,
    			    .release    = sk_release,
    				    .write      = sk_write,
    	    .read	= sk_read,
    }
    ;
    static int __init sk_init(void) {
    	printk("SK Module is up... \n");
    	if((result = sk_register_cdev()) < 0) {
    		return result;
    	}
    	return 0;
    }
    static void __exit sk_exit(void) {
    	printk("The module is down...\n");
    	cdev_del(&sk_cdev);
    	unregister_chrdev_region(sk_dev, 1);
    }
    static int sk_register_cdev(void) {
    	int error;
    	/* allocation device number */
    	if(sk_major) {
    		sk_dev = MKDEV(sk_major, sk_minor);
    		error = register_chrdev_region(sk_dev, 1, "sk");
    	} else {
    		error = alloc_chrdev_region(&sk_dev, sk_minor, 1, "sk");
    		sk_major = MAJOR(sk_dev);
    	}
    	if(error < 0) {
    		printk(KERN_WARNING "sk: can't get major %d\n", sk_major);
    		return result;
    	}
    	printk("major number=%d\n", sk_major);
    	/* register chrdev */
    	cdev_init(&sk_cdev, &sk_fops);
    	sk_cdev.owner = THIS_MODULE;
    	sk_cdev.ops = &sk_fops;
    	error = cdev_add(&sk_cdev, sk_dev, 1);
    	if(error)
    																																																																				        printk(KERN_NOTICE "sk Register Error %d\n", error);
    	return 0;
    }
    module_init(sk_init);
    module_exit(sk_exit);
  • sk5.c
  • /***************************************
       * Filename: sk_app.c
        * Title: Skeleton Device Application
    	 * Desc: Implementation of system call
    	  ***************************************/
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <fcntl.h>
    int main(void) {
    	int retn;
    	int fd;
    	// char buf[100] = "write...\n";
    	char buf[100] = {
    		0
    	}
    	;
    	fd = open("/dev/SK", O_RDWR);
    	printf("fd = %d\n", fd);
    	if (fd<0) {
    		perror("/dev/SK error");
    		exit(-1);
    	} else
    										        printf("SK has been detected...\n");
    	//retn = write(fd, buf, 10);
    	retn = read(fd, buf, 20);
    	// fd가 가르키는 파일에 buf에서 20byte 읽음
    	printf("\ndata : %s\n", buf);
    	close(fd);
    	return 0;
    }
  • sk5_app.c
  • make後insmod後検査結果
  • ioctl

  • int (ioctl) (struct inode inode, struct file *flip, unsigned int cmd, unsinged long arg);
  • cmdはどの関数を書くかを決定します
  • cmdは、引数値に基づいて正しい動作を選択するswitch文からなる.
  • SMPアーキテクチャは、カーネルコードの実行効率を向上させることを目的としています.