#pragma pack()

2008/03/05 11:26

[ 설명 ]

구조체의 바이트 정렬을 조정하기 위해서 사용을 합니다. 기본적으로 컴파일러는 4바이트, 또는 8바이트로 구조체 크기를 정렬을 하도록 되어 있습니다. 따라서, 명확하게 정의를 하지 않는다면, 5바이트의 구조체를 잡는다고 하더라도 8바이트가 기본 정렬로 되어 있으면 실제 메모리 상에서는 8바이트의 공간을 잡는다는 뜻입니다.


[ 예제 ]

#pragma pack(push,1) // 패킷 정의
typedef struct _st_Header_
{
        unsigned int     uiSrcIP;
        unsigned int     uiDestIP;
        unsigned short usSrcPort;
}st_Header, *pst_Header;
#pragma pack(pop) // 패킷 원상태로 변경

[ 형태 ]
#pragma pack(push, 정렬바이트수(ex.1,2,4,8,16))
#pragma pack(pop)

정렬하고자 하는 바이트의 수는 2의 배수로 들어갑니다.(1,2,4,8,16)

정렬바이트수(ex.1,2,4,8,16)는 2의 배수 격으로 들어 간다.
기본적으로 4인가로 설정이 되여 메모리로 전송할때.. 4바이트 단위로 전송을 하는데
14나 15로 전송이 될때 쓰레기 값으로... 2나 1바이트를 추가 시켜서 16을 강제로 만들
어서 전송합니다 (32bit Machine에선 4바이트이상 정렬일때 빠릅니다)

 
헌데 이것이.. 메모리 전송일때는 별 문제가 발생하지 않지만. 소캣을 사용하는
통신 관련일때는 문제가 되어서 그런 단위를 조정해 준다.
 
바이트정렬 방법은 2가지
 
[ 방법1 ] #pragma pack(1)

#pragma pack(1)
typedef struct _st_Info_
{
       ...
} st_Info, *pst_Info;
#pragma pack()
 
[ 방법2 ]
 
typedef struct _st_Info_
{
       ...
} __attribute__((packed)) st_Info, *pst_Info;
Posted by DOIT™
아래의 내용은 http://chonga.pe.kr/blog/index.php?pl=919 사이트에서 가지고 온 내용입니다.

다른 용도가 아니라.. 개인적으로 좋은 내용이라 가지고 있기 위해서 가지고 온 것인데.. 불펌이라면 불펌일 수도 있는데.. 순수 개인 용도라.. 이해를 해 주시길..^^

=============================================================================
제목: linux epoll을 이용한 echo server
- 작성자: 어린미르 (http://chonga.pe.kr/blog)
- 문서위치: http://chonga.pe.kr/blog/index.php?pl=919
- 작성일: 20070405
- 문서 변경 이력 :
20070405 초판 릴리즈
20070406 EPOLLONESHOT 설명 추가

선언: 본 문서는 저자의 개인적인 의견이 들어가 있을 수 있습니다. 이 곳에 게재된 내용은 상업적 판단을 위한 자료로 이용될 수 없으며 그로 인한 책임은 저자에게 없습니다.



1 개요
Linux kernel 2.6에서 네트워크 성능 향상을 위해 정식으로 릴리즈된 i/o 이벤트 통지 기능인 epoll을 이용하여 echo server의 예를 통해 간단한 개요를 살펴보도록 하자.

2 epoll이란?
Linux kernel 2.4 이전부터 select, poll의 한계를 극복하기 위해서 실험적인 i/o 모델들이 테스트되기 시작했다. /dev/poll 혹은 realtime signal(rtsignal), event poll 등이 그 대표적인 예이다. 그 와중에 event poll이라는 이름으로 진화되기 시작한 것이 지금의 epoll이라고 할 수 있다.

3 epoll의 설명
말 그대로 i/o 이벤트의 통지기능을 하고 있는데, 크게 2가지 모드를 지원한다. 하나는 Level Triggered(이후 LT)이고 또 하나는 Edge Triggered(이후 ET)라고 할 수 있다. LT는 상태의 값을 검사하는 방법이고, ET는 상태의 변화를 감지하는 방법이다.

epoll은 우선 기존의 select, poll과 마찬가지로 socket(file descriptor)의 목록을 관리하고 그 것을 어떻게 검사하는 지에 대해서는 LT와 ET의 방법이 있다고 보면 크게 다르지 않다. select와 poll의 방법은 LT의 방법이라고 보면 된다. 따라서 기존에 만들어진 select, poll의 소스코드를 epoll로 그대로 마이그레이션하는 경우에는 LT 모드로 작업을 하면 쉽게 수정을 마칠 수 있다.

3.1 epoll의 함수
epoll을 위해 간단히 3가지 함수가 제공되는데, epoll 객체를 생성하는 epoll_create와 epoll에 socket 목록을 제어하는 epoll_ctl, 그리고 socket 목록의 이벤트를 감지하는 epoll_wait다.
그리고 struct epoll_event가 있다. 더 자세한 내용은 man-page로부터 살펴보시기를 바란다.

3.1.1 struct epoll_event
typedef union epoll_data {
     void *ptr;
     int fd;
     __uint32_t u32;
     __uint64_t u64;
} epoll_data_t;

struct epoll_event {
     __uint32_t events;  /* Epoll events */
     epoll_data_t data;  /* User data variable */
};


3.1.2 관련 함수
int epoll_create(int size)
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout)


3.2 epoll의 Level Triggered 모드와 Edge Triggered 모드
epoll은 기존 socket 목록을 갖고 있는 상황에서 그 목록 중에 "읽기/쓰기/예외 상황" 등의 이벤트들이 발생을 감지해서 각각에 맞는 처리를 하게 되는 것은 공통이지만, LT와 ET의 모드에 따라 이벤트를 감지하는 방식이 달라진다고 볼 수 있다. 다시 LT를 설명하자면 epoll에 등록된 socket 목록들 가운데, 이벤트가 발생된 부분이 체크가 되어 있다고 가정하면 이벤트가 이번 턴에 발생(epoll_wait가 깨어남)하더라도 처리가 되지 않았다면 다음 턴에 다시 감지된다고 이해하면 쉽겠다. 이를 기준으로 ET를 다시 설명하면 이번 턴에 읽기 이벤트가 발생했다고 하면 이번 턴에 읽기 동작을 모두 완료하지 않는다면 다시 epoll_wait로 이벤트를 감지하는 함수가 호출되더라도 이전 동작에 의한 이벤트 감지는 불가능해진다. 따라서 LT는 상태감지, ET는 변경감지라고 할 수 있겠다. 물론 일반적으로 변경만을 감지하는 ET의 경우가 성능이 더 뛰어나다. 중요한 부분으로 ET의 경우에는 반드시 non blocking socket을 사용해야한다.

마지막으로 ET의 경우에는 추가적으로 한가지 모드를 더 지원하는데, EPOLLONESHOT이라는 모드다. 이 것은 epoll이 관리하는 socket 목록에 한 번 등록이 된 이후에, 이벤트 감지에 의해 검출이 되는 경우, socket 목록에서 이벤트를 받지 않도록 설정이 변경되는 것으로 one shot이라는 표현을 쓰고 있다. 이 경우는 이벤트를 검출한 이후에, 다른 쓰레드에 해당 socket에 대해서 read 작업을 맡기고 끝난 경우에 다시 epoll의 socket 목록에서 이벤트를 받을 수 있도록 변경하는 구조의 서버 프로그램에서 유용한 기능이라고 할 수 있겠다. 이 기능은 client 로서 동작하는 경우에 non-blocking socket 설정하고 epoll의 목록에 넣은 후에 connect를 한 후에 읽기 이벤트(접속됨)를 1회 검사하는 기능으로 사용되어도 될 듯 하다.

4 epoll의 실전 예
echo server의 구현을 통해 epoll의 실전 예를 살펴보도록 하자. 우선 LT, ET, 그리고 ET의 ONESHOT기능을 모두 이용하여 다음과 같은 예제 코드를 간단히 만들어 보았다. LT의 경우는 blocking socket으로 구현했고, ET의 경우는 non-blocking socket으로 구현되었다.

4.1 makefile의 예
make / LT 모드의 echo server 빌드
make echoserver2-et / ET 모드의 echo server 빌드
make echoserver2-etoneshot / ET 모드의 ONESHOT 기능의 echo server 빌드

CC:=gcc
CFLAGS:=
LIBS:=
all:
        $(CC) $(CFLAGS) -g -o epoll-echoserver2 epoll-echoserver2.c $(LIBS)
echoserver2-et:
        $(CC) $(CFLAGS) -DUSE_ET -g -o epoll-echoserver2 epoll-echoserver2.c $(LIBS)
echoserver2-etoneshot:
        $(CC) $(CFLAGS) -DUSE_ET -DUSE_ETONESHOT -g -o epoll-echoserver2 epoll-echoserver2.c $(LIBS)


4.2 echoserver의 예 : epoll-echoserver2.c
소스의 경우 select, poll과 크게 다르지 않다고 볼 수 있다. accept socket을 만들고 epoll에 읽기 이벤트를 설정한 후에 epoll의 socket 목록에 최초에 추가시키고 epoll_wait의 loop로 들어와서 accept socket인지 일반 socket인지에 따라 do_accept()와 do_use_fd()의 함수로 분기 호출했다. 내용 중에서 눈여겨 볼 부분은 struct epoll_event인데, events(읽기,쓰기, ET모드 설정 등)와 data이다. data의 경우에는 int타입이나 void* 타입을 마음대로 설정해서 사용할 수가 있다. 여기서는 int 타입으로 socket인 file descriptor를 넣어서 처리한다. 실제로 개발자가 원하는 사용자 객체의 타입을 데이터의 포인터로 사용자 관리 타입을 만들고 struct epoll_event의 data에 넣어줄 수도 있다.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>


#define EPOLL_SIZE 60
#define EPOLL_EVENT_SIZE 100

int
setnonblock (int sock)
{
  int flags = fcntl (sock, F_GETFL);
  flags |= O_NONBLOCK;
  if (fcntl (sock, F_SETFL, flags) < 0)
    {
      perror("fcntl, executing nonblock error");
      return -1;
    }
  return 0;
}

int
settcpnodelay (int sock)
{
  int flag = 1;
  int result = setsockopt (sock,    /* socket affected */
               IPPROTO_TCP,    /* set option at TCP level */
               TCP_NODELAY,    /* name of option */
               (char *) &flag,    /* the cast is historical  cruft */
               sizeof (int));    /* length of option value */
  return result;
}

int
setreuseaddr(int sock)
{
  int flag = 1;
  int result = setsockopt (sock,    /* socket affected */
               SOL_SOCKET,    /* set option at TCP level */
               SO_REUSEADDR,    /* name of option */
               (char *) &flag,    /* the cast is historical  cruft */
               sizeof (int));    /* length of option value */
  return result;
}



int
get_portnumber_from_arg(int argc, char **argv)
{
  // get port number
  if (argc == 2)
    {
      return atoi(argv[1]);
    }
  else
    {
      return -1;
    }
}

int
init_epoll (int eventsize)
{
  int efd;

  // init epoll
  if ((efd = epoll_create (eventsize)) < 0)
    {
      perror ("epoll_create (1) error");
      return -1;
    }
  return efd;
}

int
init_acceptsock (unsigned short port)
{
  struct sockaddr_in addr, clientaddr;

  int clilen = sizeof (clientaddr);
  int sfd = socket (AF_INET, SOCK_STREAM, 0);

  if (sfd == -1)
    {
      perror ("socket error :");
      close (sfd);
      return -1;
    }

  setreuseaddr(sfd);

  addr.sin_family = AF_INET;
  addr.sin_port = htons (port);
  addr.sin_addr.s_addr = htonl (INADDR_ANY);
  if (bind (sfd, (struct sockaddr *) &addr, sizeof (addr)) == -1)
    {
      close (sfd);
      return -2;
    }
  listen (sfd, 5);
  return sfd;
}

int
do_use_fd (int efd, struct epoll_event ev)
{
  int readn;
  int sendflags = 0;
  char buf_in[1024] = { '\0' };
  int cfd = ev.data.fd;

  //printf("DoUseFD\n");
#ifdef USE_ET
  int sizen = 0;
  char readbuf[256] = { '\0' };
  while(1) {
      readn = read (cfd, readbuf, 255);
    if (readn <0 ) {
          if (EAGAIN == errno ) {
            break;
            }
              do_del_fd(efd, cfd);
          close (cfd);
          printf ("Close fd %d by %d\n", cfd,readn);
          perror("Closed");
          return -1;
    }
    sizen += readn;
        if (sizen >= 1024) {
           do_del_fd(efd, cfd);
           close (cfd);
       printf ("Close buffer full fd %d by %d\n", cfd,readn);
       perror("Closed");
       return -1;
        }
        memcpy(buf_in,readbuf,readn);
  }
  printf ("read data %d, %s", sizen, buf_in);
  send (cfd, buf_in, strlen (buf_in), sendflags);

#ifdef USE_ETONESHOT
  // re-set fd to epoll
  do_modify_fd(efd, cfd);
#endif // USE_ETONESHOT

#else //#ifdef USE_ET

  //memset (buf_in, 0x00, 256);
  readn = read (cfd, buf_in, 255);
// if it occured ploblems with reading, delete from epoll event pool and close socket
  if (readn <= 0)
    {
      do_del_fd(efd,cfd);
      close (cfd);
      printf ("Close fd ", cfd);
    }
  else
    {
      printf ("read data %s", buf_in);
      send (cfd, buf_in, strlen (buf_in), sendflags);
    }
#endif //#ifdef USE_ET
  return 1;
}

int
do_accept (int efd, int sfd)
{
  int cfd;
  int clilen;
  struct sockaddr_in addr, clientaddr;

  printf("Accepted\n");
  cfd = accept (sfd, (struct sockaddr *) &clientaddr, &clilen);
  if (cfd < 0)
    {
      perror ("Accept error");
      return -1;
    }

#ifdef USE_ET
  setnonblock (cfd);
#endif // USE_ET
  settcpnodelay (cfd);

  do_add_fd(efd, cfd);

  return cfd;
}

int
do_add_fd(int efd, int cfd)
{
  struct epoll_event ev;

  ev.events = EPOLLIN;
#ifdef USE_ET
  ev.events |= EPOLLET;
#ifdef USE_ETONESHOT
  ev.events |= EPOLLONESHOT;
#endif // USE_ETONESHOT
#endif // USE_ET
  ev.data.fd = cfd;
  return epoll_ctl (efd, EPOLL_CTL_ADD, cfd, &ev);
}

// fixme
int
do_modify_fd(int efd, int cfd)
{
  struct epoll_event ev;

  ev.events = EPOLLIN;
#ifdef USE_ET
  ev.events |= EPOLLET;
#ifdef USE_ETONESHOT
  ev.events |= EPOLLONESHOT;
#endif // USE_ETONESHOT
#endif // USE_ET
  ev.data.fd = cfd;
  return epoll_ctl (efd, EPOLL_CTL_MOD, cfd, &ev);
}


int
do_del_fd(int efd, int cfd)
{
  struct epoll_event ev;

  return epoll_ctl (efd, EPOLL_CTL_DEL, cfd, &ev);
}


// main
int
main (int argc, char **argv)
{
  const int poolsize= EPOLL_SIZE;
  const int epollsize= EPOLL_EVENT_SIZE;
  struct epoll_event *events;
  struct epoll_event ev;
  int sfd, efd;
  int i;
  int max_got_events;
  int result;
  int port;

  port = get_portnumber_from_arg(argc,argv);
  if (port < 0)
    {
      puts("I need 1 argument(as a listen port)");
      return 1;
    }

  efd = init_epoll (epollsize);
  if (efd < 0)
    {
      perror ("init_epoll error");
      return 1;
    }

  // init pool
  events = (struct epoll_event *) malloc (sizeof (*events) * poolsize);
  if (NULL == events)
    {
      perror ("epoll_create (0) error");
      return -1;
    }

  sfd = init_acceptsock (port);
  if (sfd < 0)
    {
      perror ("init_acceptsock error");
      return 1;
    }

  printf("Running Server port %d\n",port);
  result = do_add_fd(efd,sfd);
  if (result < 0)
    {
      perror ("epoll_ctl error");
      return 1;
    }

  while (1)
    {
      max_got_events = epoll_wait (efd, events, poolsize, -1);
      for (i = 0; i < max_got_events; i++)
    {
      if (events[i].data.fd == sfd)
        {
          do_accept (efd, sfd);
        }
      else
        {
          do_use_fd (efd, events[i]);
        }
    }
    }
  return 1;
}


5 참고 문헌
- man page : man epoll
- google 에서 epoll 검색
- wikipedia 에서 epoll 검색
Posted by DOIT™
간혹 주기적으로 명령어를 쳐서 상태 정보를 확인해야 하는 경우가 있습니다.

예를 들면, 1초마다 "ipcs -a"를 쳐서, 메시지큐, 공유메모리, 세마포어에 대한 정보를 확인 한다든지..

이런 경우에 계속 명령어를 치고 있자니, 답답하고..

이럴 때에 while을 사용합니다.

[root@ipaf2 root]# while true
> do
> sleep 1
> ipcs -a
> done

위와 같이 하면, 1초마다 "ipcs -a"에 대한 결과를 화면에 뿌려 줍니다.

여러가지 케이스에서 활용할 수 있겠죠..? ^^
Posted by DOIT™
일반적으로 HDD를 사 보면, 실제 표기된 용량과 포멧 후에 사용할 수 있는 용량에 차이가 있다는 것을 알 수 있습니다.

"간 혹, 다른 HDD를 준 것이 아니냐..?" 라는 의심을 하는 사람들이 있습니다.

하지만, 이것은 표기 방법의 문제라고 할까요? 우리가 실제 사용하는 환경에서의 용량 표기와 HDD제조 업체에서 표기하는 방식의 차이에서 발생하는 문제 입니다.

우리가 사용하는 환경에서는

1KByte는 1024Bytes로 계산을 합니다. 하지만, HDD 제조 업체에서는 1000Bytes를 1KByte로 계산을 하고 있습니다. 여기에서 차이가 생기게 됩니다.

실제 HDD에서 100GBytes라고 표기가 되어 있다면, 이것은 1KByte을 1000Byts로 계산을 해서 나온 값입니다. 따라서, 이 값을 1024Bytes로 환산을 해 줘야 하는 것입니다.

간단한 계산 방법으로

실제 용량 = 표기용량 * 0.9313 을 하면 쉽게 계산이 됩니다.

120G * 0.9313 = 111.76GBytes
200G * 0.9313 = 186.26GBytes
500G * 0.9313 = 465.65GBytes

라는 계산이 나옵니다.
Posted by DOIT™

Adobe CS3 버전부터 Apple사의 Bonjour network 프로그램을 사용한다고 합니다. 따라서 CS3를 설치하게 되면 동작을 하게 됩니다. 알려진 바로는 컴퓨터의 리소스를 많이 잡아 먹어 시스템을 버벅 거리게 만듭니다. 저의 경우, V3에 걸려서 "이게 뭐지?" 하고 찾아 보다가 알게 되었지요.

Adobe사의 기술 노트 http://www.adobe.com/go/kb400982 에 Bonjour가 설치된 이유, Bonjour가 어떻게 시작되고, Bonjour를 지우는 방법이 들어 있습니다.

해당 폴더를 지우는 방법을 간단하게 설명을 드리면,

cmd를 이용하여 명령 프로프트를 열고, 해당 디렉토리로 이동을 합니다. 기본적으로 "C:\Program Files\Bonjour"에 설치가 이루어집니다.

해당 서비스를 종료 시키고,
C:\Program Files\Bonjour>mDNSResponder -remove

해당 서비스에 필요한 dll 파일의 이름을 변경합니다.
C:\Program Files\Bonjour>ren mdnsNSP.dll mdnsNSP.dll.old

그리고, 재부팅 후에 해당 폴더를 삭제 하시면 됩니다.

필요없는 기능이라(솔직히 필요한 것인지, 아닌 것인지도 잘 모름..^^) 지워 주는게 좋겠지요..^^

Posted by DOIT™

http://wiki.kldp.org/wiki.php/DocbookSgml/Bash-Prog-Intro-HOWTO#AEN14

위의 링크을 글을 참조하는게 좋을 듯 싶네요.

글의 내용을 가져다가 놓고 싶지만, Copy & Paste를 할 수도 없고(양심상^^), 그냥 바로 링크로 해 놓는게 좋을 거 같네요.

여러가지 일을 하다 보면, 간단하게 필요할 것이긴 한데, 처음부터 배운적이 없는 부분이라 다시 한번 배워 보는 것도 좋을것 같네요.

Posted by DOIT™

jwmx.. jwBrowser를 만드시는 분의 블로그에서 참조해서 가지고 온 자료입니다..^^

파일 찾기 - find

find ./NTAF/* -name "*.c" |more
현재 디렉토리의 하위인 NTAF라는 디렉토리 하위에 있는 모든 디렉토리에서 이름이 *.c로 되는 파일 찾아 줍니다.
|more는 한 화면 단위로 출력을 해 주도록 넣습니다.


문자열 찾가 - grep

grep -nr " sleep(" *
현재 디렉토리의 하위에 있는 모든 디렉토리에 있는 파일들에서 sleep( 가 들어가 있는 파일을 찾아 줍니다.
-n 옵션에 의해서 파일에서 라인 넘버까지 출력을 해 주니까 찾기 편하네요.


코딩을 하면서 사용하는 찾기 기능은 이 정도..^^

많은 기능들이 있지만, 익숙하지 않아서 그런지 잘 사용을 하지 않고, 익숙한 것만 사용하다 보니, 이 두개만 사용을 하게 되더군요.

Posted by DOIT™
debugfs 라는 명령어 입니다. (man page 참조)

실제 사용예를 들어 설명하겠습니다.

가정1) /home/pds/portsentry.tar.gz 라는 파일이 있음.
가정2) /home 파티션은 hda8 입니다. (df -h 로 확인)
가정3) rm -f /home/pds/portsentry.tar.gz 명령으로 지웠음.
가정4) root 로 작업.

복구 절차.

1. #debugfs /dev/hda8

=> 설명 : hda8 파티션에 대해서 검사를 한다.

2. debugfs:

=> 대기상태를 뜻함. 이곳에서 lsdel 을 입력하고 엔터.
계속...

debugfs: lsdel
99 deleted inodes found.
Inode Owner Mode Size Blocks Time deleted
108123 0 100644 239 1/ 1 Thu Jan 3 01:25:33 2002
18417 0 100644 426625 420/ 420 Thu Jan 3 01:26:34 2002
45007 0 100644 343 1/ 1 Thu Jan 3 01:29:59 2002
28691 0 100400 879 1/ 1 Thu Jan 3 01:38:29 2002
18394 0 40755 0 1/ 1 Thu Jan 3 01:58:54 2002
..
.
14356 0 100644 2325 3/ 3 Fri Jan 25 16:13:24 2002
61239 0 100644 43034 44/ 44 Fri Jan 25 16:13:31 2002
debugfs:

위와 같은 상태로 나오고 다시 대기상태로 됩니다. 실제로는 너무 많이 나오더군요.. (내가 그렇게 많이 지웠었나? '.'a)

이제 이 목록중에서 하나를 선택해서 살려야 합니다. 다행히도 살리고자 하는 파일은 가장 최근에 지운 파일이므로 가장 아래쪽에 있는 것이겠죠.

debugfs: dump <61239> /home/debugfs/portsentry.tar.gz

=> Inode 값을 <> 안에 적어줍니다. 뒤에는 복구할 파일 이름을 적어주시면 됩니다.
=> 복구할 파일은 다른 디렉토리로 지정해 주시는게 좋습니다. 별 상관은 없지만...

#cd /home/debugfs
#tar -zxvf portsentry.tar.gz // 정상적으로 압축이 풀리더군요.

=> 아주 훌륭하게 복구가 되었더군요. ^^v

임의로 portsentry.tar.gz 를 지워서 테스트를 한 것입니다.

debugfs: 상태에서 사용할 수 있는 명령어는 help 를 쳐보면 알 수 있습니다.
끝내는 것은 q, quit 입니다.



아래는 debugfs: 에서 사용가능한 명령어들 입니다.
---------------------------------------------------------------------

Available debugfs requests:

show_debugfs_params, params
Show debugfs parameters
open_filesys, open Open a filesystem
close_filesys, close Close the filesystem
feature, features Set/print superblock features
dirty_filesys, dirty Mark the filesystem as dirty
init_filesys Initalize a filesystem (DESTROYS DATA)
show_super_stats, stats Show superblock statistics
ncheck Do inode->name translation
icheck Do block->inode translation
change_root_directory, chroot
Change root directory
change_working_directory, cd
Change working directory
list_directory, ls List directory
show_inode_info, stat Show inode information
link, ln Create directory link
unlink Delete a directory link
mkdir Create a directory
rmdir Remove a directory
rm Remove a file (unlink and kill_file, if appropriate)
kill_file Deallocate an inode and its blocks
clri Clear an inode's contents
freei Clear an inode's in-use flag
seti Set an inode's in-use flag
testi Test an inode's in-use flag
freeb Clear a block's in-use flag
setb Set a block's in-use flag
testb Test a block's in-use flag
modify_inode, mi Modify an inode by structure
find_free_block, ffb Find free block(s)
find_free_inode, ffi Find free inode(s)
print_working_directory, pwd
Print current working directory
expand_dir, expand Expand directory
mknod Create a special file
list_deleted_inodes, lsdel
List deleted inodes
write Copy a file from your native filesystem
dump_inode, dump Dump an inode out to a file
cat Dump an inode out to stdout
lcd Change the current directory on your native
filesystem
rdump Recursively dump a directory to the native filesystem
help Display info on command or topic.
list_requests, lr, ? List available commands.
quit, q Leave the subsystem


참고로 해보지는 않았음..^^

참고로 조금만 주의를 하면.. 쓸 일이 없음.. ^^
Posted by DOIT™
^M 문자와 관련해서 게시판을 검색해 보니 다양한 방법이 소개되어 있어서 이것을 참조하여 한 문서로 정리했습니다.

Vi(m) 사용시 ^M 없애기

vi(m)을 사용하다보면 윈도우즈에서 작업한 텍스트 파일에 ^M 문자가 붙는 경우를 종종 봅니다.
특히 editplus, ultraedit 등 문서편집기에서 바로 ftp 에 업로드 하는 경우도 빈번하더군요.

현재 vim에서는 도스 문서로 읽게 되면 이 문자가 붙지 않기도 하지만, 종종 이 문자 때문에 보기가 상당히 귀찮아 보일 때가 있습니다.
특히, SQL 백업 파일을 볼 때 이 문자가 붙기도 하는데 특정한 내용을 볼 때 이런 문자가 붙은 것을 보기는 상당히 힘들죠.
(sun의 파일을 aix에서 받을 때에도 이런 문제가 발생한다고 합니다)

이 문자는 ^M은 ^+M이 아니라 Control+v+m 입니다.
따라서, 다음에 이 문자를 없앨 때도 이렇게 타이핑을 하도록 하빈다.

다음은
http://www.lug.or.kr/에 올라온 몇 개의 팁을 정리한 것입니다.
생각보다 많은 방법들이 있을 수 있겠군요.

1. vi(m)이 열린 상태
1.1 문자 치환 명령 이용

다음과 같이 문자 치환 명령으로 이 문자를 없애도록 합니다.
:1,$s/^M//g

물론 이것의 입력은 다음과 같이 하도록 합니다.
:1,$s/[Control]+v+m을 누른다.//g

1.2 파일포맷 변경

vim 5.0 이상에서는 다음과 같이 명령을 내리도록 합니다
:set fileformat=unix

혹은
:set ff=unix

그리고, 저장하고 종료합니다.
:wq

이와 반대로 끝에 ^M 을 붙이려면(과연 누가..) 다음과 같이 합니다.
:set fileformat=dos

이전버전에서는 다음과 같이 합니다.
:set textmode

2. 프롬프트 상에서
2.1 dos2unix 이용

dos2unix와 unix2dos를 이용하여 변환할 수 있습니다.

다음과 같이 하면 ^M 문자가 없어집니다.
$ dos2unix [문서명](여러 파일의 경우 *.확장자)

그리고 다음과 같이 하면 ^M 문자가 생기죠.
$ unix2dos [문서명]

2.2 cat과 tr을 이용한 방법

다음과 같이 하면 해당 파일의 ^M 문자가 없어집니다.
$ cat dos-file | tr -d ^M > unix-file

2.3 perl 스크립트

다음과 같이 하면 여러파일을 한번에 바꾸게 됩니다.
# perl -i -pe 's/\015//g' *.html


3. 다른 에디터의 사용

pico 라는 에디터 아실겁니다. 기능은 별로 없지만 빠르고 간편하죠.
vi 나 emacs 에서 ^M 으로 잡히는 것이 pico에서는 안 잡히는데, 파일을 pico로 열어서 다시 이 문서를 저장합니다.
그리고 vi 나 emacs 로 읽으면 ^M 이 모두 없어진 것을 알 수 있습니다. 쉽죠?


4. man 페이지의 ^M, ^H 문자

man 페이지를 일반 화일로 바꾸면 ^M, ^H 등이 생기는데 (예, 한컴리눅스 ^H)
다음과 같이 하면 이 문자를 없애고 볼 수 있습니다.

다음은 ls 의 예입니다.

4.1 ps 또는 pdf로 변환하기

man -t [변경시킬화일] > [변경후화일명].ps
man -t [변경시킬화일] > [변경후화일명].pdf

예)
man -t ls > ls.ps 또는 ls.pdf

4.2 텍스로 변환하기

man [변환시킬화일] | col -b> [변환후 화일명].txt
Posted by DOIT™
윈도우를 설치하면 MSN이 기본으로 설치가 됩니다. 이 경우 MSN을 삭제하는 법입니다.

시작 -> 실행 에 가서..

RunDll32 advpack.dll,LaunchINFSection %windir%\INF\msmsgs.inf,BLC.Remove

위에 것을 붙여넣기 한 다음에.. 확인.. 누르면 자동으로 삭제가 됩니다..

보통 이것을 삭제 안하고 새로운 MSN 버전을 깔게 되면, 컴퓨터가 인공지능적으로 2번 로그인을 합니다. -.-;;
예전 버전에서 한번, 그리고, 새로운 버전 한번, 따라서 순간적으로 2번 로그인 하는 신공을 펼칠 수는 있습니다.. -.-;;
Posted by DOIT™

BLOG main image
by DOIT™

공지사항

카테고리

분류 전체보기 (11)
Photo..... (0)
Computer..... (11)
My Life..... (0)

최근에 달린 댓글

최근에 받은 트랙백

Total : 3,392
Today : 0 Yesterday : 0