linux #2 basic commands #1 (리눅스 - 기본 명령어 #1)

1.시스템 레벨(Run level)

- 시스템 운영을 위해 시스템의 부팅 단계를 레벨로 표시합니다.
- 구분

0: poweroff
1: Single user mode
2: Multi user mode(CLI) commend line interface, 공유금지
3: Multi user mode(CLI) 공유가능
4: x
5: Xwindow multi user mode
6: Reboot


#init 0
#who -r  상태정보확인

2. man (On-line manual)

- 시스템에서 제공되는 명령, 파일 등에 관한 메뉴얼 정보를 보여줍니다.

# man [options] [sections] argument

*section
1 일반 명령
2 System Call
3 Library ~.so
4 특수 파일
5 구성정보 파일
6 게임 메뉴얼
7 환경 설정(환경변수) path
8 관리 명령
9 커널 관련

# man section_no argument

# man signal   == 2번 System Call에 대한 정보를 보여줍니다.
# man 7 signal == 7번 환경변수에 대한 정보를 보여줍니다.

# man passwd   == 1번 일반명령어 passwd에 대한 정보를 보여줍니다.
# man 5 passwd == 5번 특수파일 passwd에 대한 정보를 보여줍니다.

*최소 설치 시 또는 메뉴얼을 제공하지 않는 명령, 파일인경우 출력 없습니다.


3. 기본명령

1) ls(list)

- 작업 디렉터리, 대상 디렉터리 내의 파일 정보를 출력합니다.
- 명령 형식

#ls [-options] [file|dir]
#ls -l : -l long 파일이 가진 속성 정보 출력합니다. 
#ls -a : -a all 대상 디렉터리 내 숨김 속성을 갖는 파일도 출력합니다.
#ls -F : -F file type 파일의 타입 정보 4가지를 같이 출력합니다.
name/ - directory
name* - execute file
name@ - Symbolic Link
name  - file
#ls -i : -i index node 파일이 위치하고 있는 inode 정보를 포함하여 출력합니다.
#ls -lu: -u user(Access) time 파일에 접근한 시간 정보를 표시합니다.
#ls -lc: -c change time 파일의 속성 정보에 변경이 발생된 시간 정보를 표시합니다.
#ls -n : -n ID number 사용자의 ID를 표시 합니다.(ls -l에선 아이디와 그룹이 영어로 표시)

2) cd (change directory)

- 명령 형식

#cd directory

#cd       : home디렉토리로 이동합니다.
#cd ..    : 상위 디렉토리 이동합니다.
#cd -     : 이전 작업 디렉토리로 이동합니다.
#cd ~     : home디렉토리로 이동합니다.

pwd(print working drectory): 현재디렉토리

3) touch

- 파일이 없을 경우 0kb파일 생성합니다. (체크포인트 파일 일부 백업할 때 씀)
- 존재하는 파일 및 디렉토리에 적용 시간 정보 변경합니다.
- log파일을 만들 때에도 사용합니다.
- 명령 형식

#touch [-options] file/dir

#touch newfile (0kb 파일 생성)
#touch exist_file (시간 정보 변경)
#touch -t [년도]월일시분.초 file    (원하는 시간으로 변경)

4) mkdir

- 명령 형식

#mkdir [-option] new_dir
#mkdir dir1 dir2 
#mkdir dir3/dir4 - 오류
#mkdir -p dir3/dir4 - 됨 : -p path 생성도리 디렉터리의 중간 경로가 없을 때 같이 생성합니다.

5) rm

- 파일 대상 명령으로 디렉토리는 삭제 불가능합니다.
- 명령 형식

#rm [-options] file|dir

#rm file1 file2
#rm -r dir3     (-r recursive : 디렉토리 내 파일에 rm 적용 후 최종 디렉토리까지 삭제)
#rm -i file3    (-i interactive : 지우기 전 사용자에게 질의) 
           --> 해당 기능의 강제적 사용을 위한 alias 설정을 해둡니다.

*alias 기능 (alias 별명='명령 -옵션')
*alias 별명 - 현재 설정 사항 확인 가능
*unalias 별명 - 해제

6) mv (move)

- 파일을 이동할 때 사용되는 명령입니다.
- 파일의 이름을 변경할 때 사용합니다.
- 명령 형식

#mv file|dir dir            (이동)
#mv file|dir new_name (이름변경)
#mv -i file dir              (이동 할 디렉토리 내 같은 이름이 존재 할 경우에만 사용자에게 질의)

7) cat

- 짧은 텍스트 파일을 볼 때 사용합니다.(view 명령)
- 명령 형식

#cat [-option] text

#cat -n text  (-n : line Number 출력 텍스트에 라인번호 삽입)
#nl text (text 출력 시 라인번호를 포함하여 출력합니다.) (cat -n text와 동일)

Symmetric Cipher Model #1 (고전암호 대칭 암호 모델 #1)

용어정리

plaintext(평문) - 원래의 메세지
ciphertext(암호문) - 코드화된 메세지
enciphering(암호화)/encryption(암호) - 평문을 암호문으로 변환
deciphering(복호화)/decryption(복호) - 암호문을 평문으로 변환
cryptography(암호기법) - 암호에 사용된 기법들의 연구 분야
cryptographic system(암호 시스템)/cipher(암호법) - 모든 암호 기법들
cryptanalysis(암호해독) - 세부 지식 없이 메세지를 복호화 하는데 사용되는 기술 분야
cryptology(암호학) - 암호학과 암호 해독 분야를 합함

Symmetric Cipher Model (대칭 암호 모델)

대칭 암호 기법은 5가지 요소로 구성됩니다.

  • 평문 - 원래의 메세지
  • 암호 알고리즘 - 평문에 대해 치환 및 면환을 수행하는 것
  • 비밀키 - 평문을 암호화 시키는데 사용되는 키
  • 암호문 - 암호 알고리즘의 출력으로 생성된 혼합 형태의 메세지로 평문과 키에 의해 결정
  • 복호 암호문 - 암호 알고리즘을 역으로 수행하는 것
전통 암호 보안에 두 가지 요구조건
  1. 강력한 암호 알고리즘이 필요
  2. 송신자와 수신자는 비밀키를 안전한 방법으로 전달받아야함.













여기서 암호문과 암호/복호 알고리즘으로는 메세지를 복호화 할 수 없다고 가정합니다. 다시 말해 알고리즘 자체는 비밀로 할 필요가 없으며, 키만 비밀로 간직하면 됩니다.

Y=E(K,X)
X=D(K,Y)



















암호학

암호 시스템은 세 가지의 독립된 영역으로 특징지어진다.

  1. 평문을 암호문으로 변환하는데 사용되는 연산자 유형 - 치환(substitution), 전치(transposition)
  2. 사용된 키의 개수 - 서로 같은키를 이용할때: 대칭키(symmetric), 단일키(single-key), 비밀키(secret-key), 관용(conventional) 서로 다른키를 이용할 때: 비대칭(asymmetric),2-키(two-key), 공개키(public-key)
  3. 평문이 처리되는 방법 - 블럭 암호(block cipher) 입력 한번에 하나의 원소 블럭씩 처리. 스트림 암호(stream cipher)입력 요소를 연속 처리.
암호 해독 및 전사적 공격
  • 암호 해독(Cryptanalysis) - 특정 평문 또는 사용된 키의 추론을 시도하기 위하여 알고리즘의 특성 활용.
  • 전사적 공격(Brute-force attack): 하나의 암호문에 대해 평문으로 전환이 가능한 모든 키를 시도
Stallings, William. Cryptography & Network Security 5th ed..


Security #1 (보안)

Security

정보 보안은 정보를 훼손하려는 행위(Security Attack)로 부터 서비스 (Security Service)를
제공하여 공격으로부터 Detect(탐지), Prevent(방지), Recover(복구) (Security Mechanism) 하는 행위입니다.

Security Attack(공격 유형)































공격 유형으로는 크게 4가지로 볼 수 있습니다.

1. Interruption(정보 차단) 전달 되어지고 있는 정보를 중간에서 차단해 버리는 공격입니다. -> 가용성(Availability)에 영향을 줍니다.
2. Interception(정보 가로채기) 전달 되어지고 있는 정보를 중간에서 가로채는 공격입니다. -> 기밀성(Confidentiality)에 영향을 줍니다.
3. Modification(정보 변조) 전달 되어지고 있는 정보를 가로채 변조하는 공격입니다. -> 무결성(Integrity)에 영향을 줍니다.
4. Fabrication(정보 위조) 전달 되어지고 있는 정보를 위조하는 공격입니다. -> 무결성(Authenticity)에 영향을 줍니다.

결국 보안의 목표는 Availability, Integrity, Confidentiality, Authentication을 보장 하는 것 입니다.

A Model for Network Security (네트워크 보안 모델)

인터넷에서 하나의 메세지가 다른 한 쪽으로 전송될때 이 처리과정에서 양쪽 통신주체(principals)는 메세지 교환을 위해 상호 협조해야 하는데, 이는 통신 주체간의 통신 프로토콜의 협조로 개설됩니다.




안전한 전송을 위해서는 신뢰할 수 있는 제 3자가 필요합니다.


Stallings, William. Cryptography & Network Security 5th ed..


Data structures - 1. tree :: namecart program(자료구조 - 트리 명함 프로그램)




#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include <conio.h>

typedef struct namecard{
 struct namecard *left;
 char company[30];
 char position[20];
 char name[20];
 char tel[20];
 struct namecard *right;
}NC;

int Input(NC *root, NC input_tree);
void Output(NC *tree);
NC *Search(NC *tree, char *key);
void Update(NC **tree, char *key, int data_num);
void Delete(NC **tree, char *key);
int Loaddata(NC **tree, char *loadfile);
void Savedata(NC *tree, int data_num, char *loadfile);

char list[4][9]={"Company","Position","Name","Tel"};

#include <ham.h>

main()
{
 NC *tree=NULL, *ptr;
 NC input_tree; // 입력받을거

 int data_num=0;
 int i=0,j;
 char ch;
 char name_key[20];  // 검색 이름
 char loadfile[50];

 printf("로드할 데이터의 위치를 입력하세요\n::");
 scanf(" %s",loadfile);
 system("cls");

 data_num=Loaddata(&tree, loadfile);
 

 while(1)
 {

  printf("Namecard Management Program\n");
  printf("===========================\n");
  printf("*DATA INPUT(I)\n");
  printf("*DATA OUTPUT(O)\n");
  printf("*DATA SEARCH(S)\n");
  printf("*DATA UPDATE(U)\n");
  printf("*DATA DELETE(D)\n");
  printf("*****EXIT(E)*****\n");
  printf("Select the work to do : ");
  scanf(" %c", &ch);
 
  if(ch >= 'A' && ch <= 'Z')
  {
   ch += 'a'-'A';
  }

  switch(ch){
  case 'i':
  
   printf("Namecard data Input\n입력을 마치려면 (x x x x) 입력\n");
   printf("Company    Positon    Name    Tel\n");
   printf("========================================\n");
 
   while(1)
   {
    scanf(" %s %s %s %s", input_tree.company, input_tree.position, input_tree.name, input_tree.tel);
    if(strcmp(input_tree.company,"x")==0) break;
    if(!tree){
    tree=(NC*)malloc(sizeof(NC));
    strcpy(tree->company,input_tree.company);
    strcpy(tree->position,input_tree.position);
    strcpy(tree->name,input_tree.name);
    strcpy(tree->tel,input_tree.tel);
    tree->left=tree->right=NULL;
    data_num++;
    }
    else{
     Input(tree,input_tree);
     data_num++;
    }
   }
   printf("Enter...");
   getch();

   break;
  

  case 'o':

   printf("%15s\t%10s\t%10s\t%10s\n",list[0],list[1],list[2],list[3]);
   printf("==============================================================\n");
   Output(tree);
   printf("Enter...");
   getch();

   break;

  case 's':

   printf("검색할이름 입력: ");
   scanf("%s", name_key);
   ptr=Search(tree, name_key);
   if(ptr){
    printf("%15s\t%10s\t%10s\t%10s\n",list[0],list[1],list[2],list[3]);
   printf("==============================================================\n");
    printf("%15s\t%10s\t%10s\t%10s\n", ptr->company, ptr->position, ptr->name, ptr->tel);
   }
   else
    printf("없는 명함입니다.\n");
   printf("Enter...");
   getch();

   break;

  case 'u':

   printf("수정할 이름 입력: ");
   scanf(" %s", name_key);
   ptr=Search(tree, name_key);
   if(ptr){
    Update(&tree, name_key, data_num);
   }
   else
    printf("없는 명함입니다.\n");
   printf("Enter...");
   getch();   

   break;

  case 'd':

   printf("삭제할 이름 입력: ");
   scanf(" %s", name_key);
   ptr=Search(tree, name_key);
   if(ptr){
    printf("삭제하였습니다.\n");
    Delete(&tree,name_key);
   }
   else
    printf("없는 명함입니다.\n");
   
   printf("Enter...");
   getch();

   break;

  default:
   break;
  }

  if(ch == 'e'){
   FILE *f;

   f=fopen(loadfile, "wt");
   fclose(f);

   Savedata(tree,data_num,loadfile);
   break;
  }

  system("cls");
  }
}

int Input(NC *root, NC input_tree)
{
 NC *tptr = root, *before;
 int cmp;

 while (tptr)
 {
  cmp = strcmp(input_tree.name, tptr->name);
  if(cmp < 0)
  {
   before = tptr;
            tptr = tptr -> left;
  }
  else if(cmp > 0)
  {
   before = tptr;
            tptr = tptr -> right;
  }
  else{
   before = tptr;
   tptr = tptr -> right;
  }
   //return 0;  
 }
 tptr = (NC *)malloc(sizeof(NC));
 strcpy(tptr->company,input_tree.company);
 strcpy(tptr->position,input_tree.position);
 strcpy(tptr->name,input_tree.name);
 strcpy(tptr->tel,input_tree.tel);
 tptr->left = tptr->right = NULL;
 if(cmp < 0) before -> left = tptr;
 else before -> right = tptr;
    return 1;
}

NC *Search(NC *tree, char *key)
{
 NC *tptr=tree;
 int cmp;
  
 while(tptr)
 {
  cmp = strcmp(key, tptr->name);
  if(cmp < 0)
   tptr=tptr->left;
  else if(cmp > 0)
   tptr=tptr->right;
  else       // FOUND !!
   return tptr;
 }

 return NULL;      // NOT FOUND
}

void Delete(NC **tree, char *key)
{
 NC * previous, * parent, * del, * move = NULL;
 
    previous = del = * tree;
 
    while(del){
        if(strcmp(del->name, key) == 1){
            del = (previous = del)->left;
        }else if(strcmp(del->name, key) == -1){
            del = (previous = del)->right;
        }else{
            break;
        }
    }
   
    if(del == NULL){ return; }

    if(del->left){
        move = (parent = del)->left;
        while(move->right){
            move = (parent = move)->right;
        }   
        move->right = del->right;
        if(parent != del){
            parent->right = move->left;
            move->left = del->left;
        }
    }else if(del->right){
        move = (parent = del)->right;
        while(move->left){
            move = (parent = move)->left;
        }    
        move->left = del->left;
        if(parent != del){
            parent->left = move->right;
            move->right = del->right;
        }
    }else{
        (strcmp(previous->name, key) == 1) ? previous->left = NULL : previous->right == NULL;
    }
 
    if(del == previous){
        * tree = move;
    }else if(move != NULL){
        if(strcmp(previous->name, key) == 1){
            previous->left = move;
        }else{
            previous->right = move;
        }
    }
    free(del);
}

void Output(NC *tree)
{
 NC *tptr=tree;

 if(tptr == NULL)
  return;
 Output(tptr->left);
 printf("%15s\t%10s\t%10s\t%10s\n", tptr->company, tptr->position, tptr->name, tptr->tel);
 Output(tptr->right);
}

void Update(NC **tree, char * key, int data_num)
{
 NC tmp;
 printf("새 데이터 입력입력\n");
 printf("Company    Positon    Name    Tel\n");
 printf("========================================\n");
 scanf("%s %s %s %s", tmp.company, tmp.position, tmp.name, tmp.tel);
 printf("%15s\t%10s\t%10s\t%10s\n",list[0],list[1],list[2],list[3]);
 printf("==============================================================\n");
 tmp.left=tmp.right=NULL;
 if(data_num==1){
  **tree=tmp;
  Delete(tree,key);
  printf("%15s\t%10s\t%10s\t%10s\n", tmp.company, tmp.position, tmp.name, tmp.tel);
  return;
 }
 Input(*tree,tmp);
 Delete(tree,key);
 printf("%15s\t%10s\t%10s\t%10s\n",tmp.company, tmp.position, tmp.name, tmp.tel);
}

int Loaddata(NC **tree, char *loadfile)
{
 NC *ptr;
 NC tmp;
 int data_num,i;
 
 FILE *f;


 if(!(f=fopen(loadfile, "rb"))){
  return 0;
 }
 
 fseek(f,0,SEEK_END);
 if(ftell(f)==0){
  fclose(f);
  return 0;
 }

 fseek(f,0,SEEK_SET);

 ptr=(NC*)malloc(sizeof(NC));

 fscanf(f,"%d",&data_num);
 fread(ptr,sizeof(NC),1,f);
 ptr->left=ptr->right=NULL;
 *tree = ptr;

 if(data_num==1){
  fclose(f);
  return 0;
 }

 for(i=1;i<data_num;i++){
  fscanf(f,"%d",&data_num);
  fread(&tmp,sizeof(NC),1,f);
  Input(*tree,tmp);
 }
 fclose(f);
 return data_num;
}

void Savedata(NC *tree, int data_num, char *loadfile)
{
 FILE *f;

 if(!(f=fopen(loadfile, "ab"))){
  printf("error");
 }
 
 if(tree == NULL){
  fclose(f);
  return;
 }

 Savedata(tree->left, data_num, loadfile);
 fprintf(f,"%d",data_num);
 fwrite(tree,sizeof(NC),1,f);
 Savedata(tree->right, data_num, loadfile);
}



































linux kernel Module programming #2 Device driver (리눅스 커널 모듈 프로그래밍 #2 디바이스 드라이버)



#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<asm/uaccess.h>
#include<linux/cdev.h>

#define DEVICE_NAME "Minibuf"
#define BUFFER_LEN 1024
#define DEV_MAJOR 254
#define DEV_MINOR 5

static int s_bDeviceOpen = 0;
static char s_strBuf[BUFFER_LEN];
static int s_nBufPos = 0, s_nBufEnd = 0;

static int device_open(struct inode *inode, struct file *filp);
static int device_release(struct inode *inode, struct file *filp);
static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t *offset);
static ssize_t device_write(struct file *filp, const char *buffer, size_t length, loff_t *offset);

static int is_buffer_empty(void);
static int is_buffer_full(void);
static int read_buffer_char(char *buffer);
static int write_buffer_char(char *buffer);

struct file_operations device_fops = {
 read: device_read,
 write: device_write,
 open: device_open,
 release: device_release
};

static struct cdev minibuf_cdev = {
 .owner = THIS_MODULE,
 .ops = &device_fops,
};

dev_t dev_num = -1;
struct cdev *dev_ptr = NULL;

int __init init_minibuf(void)
{
 printk("Loading MiniBuffer Module\n");

 dev_num = MKDEV(DEV_MAJOR, DEV_MINOR);
 register_chrdev_region(dev_num, 1, DEVICE_NAME);
 dev_ptr = cdev_alloc();
 cdev_init(dev_ptr, &device_fops);
 cdev_add(dev_ptr, dev_num, 1);

 strcpy(s_strBuf, "Hello, World\n");
 s_nBufEnd = strlen(s_strBuf)+1;
 return 0;
}

void __exit exit_minibuf(void)
{
 printk("Unloading Minibuffer Module\n");

 unregister_chrdev_region(dev_num, 1);
}

int device_open(struct inode *inode, struct file *filp)
{
 printk(DEVICE_NAME ": Device open (%d, %d)\n", MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
 if(s_bDeviceOpen)
 {
  printk(DEVICE_NAME ": Device already open\n");
  return -EBUSY;
 }

 ++s_bDeviceOpen;
 return 0;
}

int device_release(struct inode *inode, struct file *filp)
{
 printk(DEVICE_NAME ": Device release (%d, %d)\n", MAJOR(inode->i_rdev),MINOR(inode->i_rdev));

 if(!s_bDeviceOpen)
 {
  printk(DEVICE_NAME ": Device has not opened\n");
  return -EINVAL;
 }

 --s_bDeviceOpen;
 return 0;
}

ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t *offset)
{
 int count = 0;
 if(is_buffer_empty())
 {
  printk(DEVICE_NAME ": Read return EOF\n");
  return 0;
 }

 while(!is_buffer_empty() && length > 1)
 {
  read_buffer_char(buffer);
  ++buffer;
  --length;
  ++count;
 }

 put_user(0, buffer);
 ++count;

 printk(DEVICE_NAME ": Read %d bytes\n", count);
 return count;
}

ssize_t device_write(struct file *filp, const char *buffer, size_t length, loff_t *offset)
{
 return -ENOSYS;
}

int is_buffer_empty(void)
{
 return (s_nBufPos == s_nBufEnd) ? 1 : 0;
}

int is_buffer_full(void)
{
 int pos = s_nBufEnd + 1;
 if(pos == BUFFER_LEN)
  pos = 0;
 return (pos == s_nBufPos) ? 1 : 0;
}

int read_buffer_char(char *buffer)
{
 if(is_buffer_empty())
  return -1;

 put_user(s_strBuf[s_nBufPos], buffer);

 if(++s_nBufPos == BUFFER_LEN)
  s_nBufPos = 0;

 return 0;
}

int write_buffer_char(char *buffer)
{
 if(is_buffer_full())
  return -1;

 get_user(s_strBuf[s_nBufEnd], buffer);
 if(++s_nBufEnd == BUFFER_LEN)
  s_nBufEnd = 0;

 return 0;
}

module_init(init_minibuf);
module_exit(exit_minibuf);
MODULE_LICENSE("GPL");













































C language - 6. pointer(포인터)

1.  메모리와 주소

컴퓨터의 메인메모리는 1byte 단위로 각각 주소가 16진수의 고정된 값이 배정되며 오른쪽 그림을 예를 들어 int(4bytes)형 변수 a를 선언 한다고 했을 때 임의의 연결된 4bytes의 공간에 int형 변수 a가 배정되게 됩니다. 이 때 배정된 4개의 공간중 가장 작은 주소값인 0x000102가 변수 a의 메모리 주소값이 됩니다. 









2. 포인터란?

포인터는 메모리의 주소값을 저장할 수 있는 변수로 어셈블리어, C, C++ 등 하위레벨까지 제어 할 수 있는 언어들에서 많이 쓰이며 Java나 타 언어들에선 쓰이지 않습니다.
포인터의 선언은 위와 같이 자료형과 변수명 사이에 *만 추가하면 됩니다.

일단 선언하게 되면 자료형에 관계없이 기계나 OS에 맞춰서 일정한 크기(대부분 4byte)가 주어져
변수를 보면 우리가 알고 있는 크기들로 나왔지만 포인터들은 모두 4byte로 나오는 것을 볼 수 있습니다. 또한 배열은 모두 10의 크기를 주었기 때문에 그에 10배에 해당되는 크기를 가지고 있습니다.

3. 포인터의 심화

포인터는 간단히 말해서 주소를 저장하는 공간 이라고 말할 수 있습니다만 실제론 기능을 더 가지고 있습니다.
기본자료형을 선언했을 때에는 각 자료형마다 저장될 크기와 읽어들인 2진수를 변환하는 방법이 다릅니다.

마찬가지로 포인터 또한 선언된 자료형에따라 읽어들일 크기와 2진수의 변환하는 방법이 다릅니다.

위 그림은 임의의 자료형 p를 char형 int형 double형 포인터들이 가리킬때 가져오는 값을 주소하나에 1비트씩 저장되있다고 가정했을때 만든것입니다. 위와같이 같은곳을 가리키더라도 선언된 자료형에 따라 가져오는 값이 달라질 수 있습니다.

또한 가져오는 값이 같은 상황에서도 2진수를 변환하는 방법이 고정소수점방식이냐 부동소수점방식이냐 혹은 signed냐 unsigned냐에 따라 얻어지는 값이 달라질 수 있습니다.

4. 결론

포인터에 저장되는 값은 단순 주소값이기는 하나, 선언된 자료형에 따라 얻어지는 값이 달라질 수 있다.

다중포인터를 보면 int ** a, long ***** b 이런식으로 되있지만 단순하게 생각해서 *의 개수만큼 변수에 저장된 값의 주로소 이동하면 선언된 자료형의 값이 저장되있다는 뜻이 됩니다.

 long ***** b를 보게되면 아래와 같이 되어있다고 보면 되겠습니다


linux kernel Module programming #1 (리눅스 커널 모듈 프로그래밍)

커널은 기본적으로 두가지로 나누어집니다.
첫번째로는 Monolithic-Kernel(일체형)이 있고 Micro Kernel이 있습니다.

  • Monolithic-Kernel 
    • 리눅스나 윈도우등에서 사용되는 Monolithic-Kernel은 일체형 커널로써 프로세스관리나 메모리관리 파일시스템등이 커널에 포함되어 있습니다. 그래서 운영체제의 기능을 불러오기 위해선 시스템 콜을 이용합니다.
  • Micro-Kernel 
    • 커널을 필요한 만큼만 남겨서 소영화 한 것으로 주로 임베디드 시스템에 사용됩니다. 주로 처리제어나 장치 구동 등 하드웨어에 의존하는 기능, 실시간 처리에 필요한 기능만 갖춥니다.

기본적으로 일체형 커널을 사용하게 되면 커널의 일부를 수정했을때 다시 커널 컴파일을 해야한다는 단점이 있습니다.

그 단점을 해소하기 위해 커널에 동적으로 코드를 로드, 언로드하는 것이 모듈 프로그래밍 입니다.

1. 먼저 module-init-tools 패키지를 설치해줍니다.



2. hello.c 파일을 작성줍니다.



init_hello 함수는 모듈이 시스템에 로드될때 동작합니다.
exit_hello 함수는 모듈이 시스템에서 제거될때 동작합니다.

3. Makefile 파일을 작성해줍니다.



4. 작성이 끝났으면 make 명령어를 실행해줍니다.



5. 파일이 생성된 것을 확인 할 수 있습니다.



6. insmod를 이용하여 모듈을 커널에 올리고 lsmod를 이용하여 확인해줍니다.



7. rmmod를 이용하여 모듈을 커널에서 내려주고 lsmod를 이용하여 확인해줍니다.



8. dmesg를 이용하여 동작을 확인합니다.