본문 바로가기
코스웨어/13년 스마트컨트롤러

20130703 정리

by 알 수 없는 사용자 2013. 7. 3.
728x90
반응형

 

 

시그널(SIGTERM), kill 명령

 

kill : 프로세스에 신호(종료신호)를 명시적으로 보낼때 사용하는 명령어    

 

=> kill 프로세스ID

 

 시그널(신호)

유발 사건 

디폴트 동작 

   SIGTERM

   kill 프로세스ID 명령에 따른 종료

   종료

 

 

ps (process list)

ps : 현재 창에서 돌고있는 프로세스(프로그램)을 보여줌

ps -A : 현재 돌고있는 모든 프로세스(프로그램)을 보여줌

ps -A | grep 프로그램명 : 현재 돌고있는 해당 프로세스(프로그램)의 정보(프로세스ID)를 보여줌

 

 

 

 

 getpid(), 프로그램이 자신의 프로세스ID를 얻을때 쓰는 함수

 

#include <unistd.h>

  pid_t getpid(void);
  pid_t getppid(void);


 ☞ getpid는 현재 프로세스의 프로세스 ID를  돌려준다. 

 ☞ getppid능 현재 프로세스의 부모 프로세스 ID를 돌려준다.

 

 

 

pcap.c (추가된 내용만...)

#include <signal.h>

 

int main()

      struct sigaction stAct;          //sigaction을 하기 위한 구조체 변수 

      stAct.sa_handler = Smart;   // 핸들러 등록
      sigfillset(&stAct.sa_mask);   // 다른 시그널 모두 차단
      stAct.sa_flags = 0;

 
      sigaction(SIGINT, &stAct, 0); //Ctrl + C 눌렀을때 디폴트 동작이 아닌 등록한 핸들러함수가 수행 되도록 함.

      sigaction(SIGTERM, &stAct, 0); // kill 프로세스ID  명령 쳤을때 디폴트 동작이 아닌 핸들러 함수가 수행되도록함.

 

      return 0;

}

 

void Smart(int ia)// SIGINT 핸들러, SIGTERM 핸들러 
{
       printf("Packet analyzer를 종료합니다.\n");
   
       pcap_close(stDes); //pcap 닫음
 
       exit(0);

 

 

 

 

 

 

 

 

 

 

 

 넌블로킹 입출력

 원하지 않는 블로킹 문제를 해결하는 방법으로 소켓의 동작을 변경시켜 모든 호출이 넌블로킹이 되게 하는 것이 있다.

 

 디폴트 블로킹 동작을 fcntl() ,file control 함수를 호출하여 변경할수 있음!!! 

 

 int fcntl(int fd, int cmd, long arg);

 int fcntl(int fd, int cmd, struct flock * lock);

 

 ※ 1번째 인자 : 적합한 파일(또는 소켓) 식별자이어야 함.

     2번째 인자 : 수행될 연산을 지정, 해당 식별자와 관련된 플래그들에 의해 제어되는데 

                       F_GETFL , FSETFL 등의 명령어들에 의해 지정할수 있음.

     3번째 인자 : 새로운 플래그를 적어줌, 넌블로킹 동작을 제어하는 플래그는 O_NONBLOCK 임.

                      (소켓 플래그들을 얻어 올때 arg는 0 이다.) 

 

F_GETOWN

 파일 기술자  .IR  fd상에서  이벤트들에  대한  SIGIO 그리고  SIGURG 시그널들을

 수신하는 프로세스 ID 또는 프로세스 그룹을 얻는다.

F_SETOWN

 

 파일 기술자  .IR  fd상에서  이벤트들에  대한  SIGIO 그리고  SIGURG 시그널들을

 수신하는 프로세스 ID 또는 프로세스  그룹을   설정한다.   

 

F_GETSIG

 

 입력  또는  출력이  가능해질때, 시그널이 전송되도록 한다. 제로 값은 SIGIO가

 전송되었다는 것을 의미한다.

 

F_SETSIG

 

  입력  또는  출력이  가능해질때, 시그널이 전송되도록 설정한다. 제로 값은

 디폴트 SGSIO 시그널을  전송하는 것을  의미한다. 다른 값(SIGIO을 포함)은

 대신 보내진 시그널이다.

 

F_GETFL

 

  기술자의 플래그를 읽는다. 

 

F_SETFL

  

  arg 에   의해  지정된  값을  기술자의  플래그로 설정한다. 

 

 

                    
              

 

                    

 비동기적 입출력(Asynchronous I/O)

 

☞ 비동기적 입출력 : 운영체제가 소켓호출이 성공적이었을때 프로그램에 알려줌으로써 프로그램은 소켓이 무슨일인가를

                               발생시킬 준비가 되었음을 알려 올때까지 다른 일을 하면서 시간을 보낼수 있음.

                           (임의의 입출력 관련 이벤트가 소켓에 발생하였을때 SIGIO 시그널를 프로세스에 전달하는 방식으로 동작)

 

    

 

 SIGIO를 위한 제어 3단계

 

 1.sigaction()을 이용하여 SIGIO와 핸들러 함수를 연결함.     예> sigaction(SIGIO, &handler, 0)

 

 2. 해당 소켓에 관련된 신호들을 해당프로그램(프로세스)에 전달하도록 fcntl() 함수를 이용하여

    해당 프로그램(프로세스)를 소켓의 소유자로  만듬 , 쉽게 말해 네트워크(소켓)와 APP을 연결 시켜줌

    예> fcntl(sock, FSETOWN, getpid()) , 프로세스ID를 인자로 넘겨줌으로써 해당 소켓과 연결 시켜줌

                                     

 3. fcntl() 을 이용하여 해당 소켓에 플래그(FASYNC)를 지정함으로써 비동기적 입출력을 설정함.

    예> fcntl(sock, F_SETFL, O_NENBLOCK | FASYNC)

 

 

 

 

 

 

 

 

 

 

 

 

 UDPserver.c

 

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>

#define ECHOMAX 255


void SIGINT_handler(int ia);// SIGINT 핸들러

int iSock;

 

int main()
{


 struct sockaddr_in echoServAddr;
 struct sockaddr_in echoClntAddr;
 unsigned int cliAddrLen;
 char echoBuffer[ECHOMAX];
 unsigned short echoServPort;
 int recvMsgSize;
 int iRet;

 struct sigaction stAct; //sigaction을 하기 위한 구조체 변수
    
 stAct.sa_handler = SIGINT_handler; // 핸들러 등록
 sigfillset(&stAct.sa_mask); // 다른 시그널 모두 차단
 stAct.sa_flags = 0;
 
 sigaction(SIGINT, &stAct, 0); //Ctrl + C 눌렀을때 디폴트 동작이 아닌 핸들러 함수를 호출하여 종료
   
 
 iSock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); //소켓 생성


 if(0  > iSock)
 {

       printf("Socket() failed\n");

       return 0;

 } 

 

 memset(&echoServAddr, 0, sizeof(echoServAddr));// 구조체 0으로 초기화

 echoServAddr.sin_family = AF_INET; //어드레스 패밀리
 echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); 
 echoServAddr.sin_port = htons(9999);

 

 iRet = bind(iSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr));

 

 if(0 > iRet)
 {

  printf("bind() failed\n");

  close(iSock);

  return 0;

 }

 

 cliAddrLen = sizeof(echoClntAddr);//구조체 크기


 while(1)
 {

  recvMsgSize = recvfrom(iSock, echoBuffer, ECHOMAX, 0,
                        (struct sockaddr *) &echoClntAddr, &cliAddrLen); 

  // 1번째 인자 : 소켓번호, 2번째 인자 : 버퍼주소 
  // 3번째 인자 ECHOMAX : 한번에 수신할수 있는 최고크기 
  // 5번째 인자 : 패킷 Src 주소, 6번째 인자 : 주소저장용 구조체의 크기 

  

  echoBuffer[recvMsgSize] = 0; //문자열로 만들기 위해 Null 넣어줌

  printf("%s : ", inet_ntoa(echoClntAddr.sin_addr));// 클라이언트의 주소 출력

  printf("%s\n", echoBuffer); // 전송받은 데이터 출력

 

 }

 

 return 0;


}

void SIGINT_handler(int ia) // SIGINT 핸들러
{
     printf("UDP Server를 종료합니다.\n");
     close(iSock); //소켓  닫음
  
     exit(0);
}

 

 

 

 

 UDPclient.c

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>

#define ECHOMAX 255


void SIGINT_handler(int ia);// SIGINT 핸들러

 

int iSock;

 

int main(int argc, char * argv[])
{


 struct sockaddr_in echoServAddr;
 struct sockaddr_in echoClntAddr;
 unsigned int servAddrLen;
 char echoBuffer[ECHOMAX];
 unsigned short echoServPort;
 int recvMsgSize;
 int iRet;

 struct sigaction stAct; // sigaction을 하기 위한 구조체 변수
   
 stAct.sa_handler = SIGINT_handler; // 핸들러 등록
 sigfillset(&stAct.sa_mask); // 다른 시그널 모두 차단
 stAct.sa_flags = 0;
 
 sigaction(SIGINT, &stAct, 0); //Ctrl + C 눌렀을때 핸들러 호출되도록...   
 
 iSock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);


 if(0  > iSock)
 {

       printf("Socket() failed\n");

       return 0;

 } 

 

 memset(&echoServAddr, 0, sizeof(echoServAddr));// 구조체 0으로 초기화

 echoServAddr.sin_family = AF_INET;

 
 if(2 == argc) // 클라이언트 실행시킬때 연결하고자 하는 IP어드레스가 입력되면...
 {
       echoServAddr.sin_addr.s_addr = inet_addr(argv[1]);
 }
 else // 입력되지 않았을때...
 { 
       echoServAddr.sin_addr.s_addr = inet_addr("192.168.10.48");
 }
 
 echoServAddr.sin_port = htons(9999);


 servAddrLen = sizeof(echoServAddr);//구조체 크기

 

 while(1)
 { 

  printf("메시지를 입력하세요\n");
  
  iRet = read(0, echoBuffer, ECHOMAX); //키보드로 부터 메시지 입력받음 
      
  sendto(iSock, echoBuffer, iRet-1, 0,  (struct sockaddr *) &echoServAddr, servAddrLen); 

  // 1번째 인자 : 소켓번호, 2번째 인자 : 버퍼주소
   // 3번째 인자 : 보낼 데이터의 크기(바이트), 키보드로 입력한 값에 비례 
   // 5번째 인자 : 패킷 Des 주소, 6번째 인자 : 주소저장용 구조체의 크기


 }
 


 return 0;


}

 

void SIGINT_handler(int ia) // SIGINT 핸들러
{
     printf("UDP Client를 종료합니다.\n");
     close(iSock); //소켓  닫음
  
     exit(0);
}

UDP [ user datagram protocol ] :  정보를 주고받을 때, 서로 주고받는 형식이 아닌 한쪽에서

                                                                     일방적으로 보내는 방식의 통신 프로토콜이다.

 

 UDP는 사용자 데이터그램 프로토콜(user datagram protocol)의 줄임말이다. 인터넷상에서 서로 정보를 주고받을 때 정보를 보낸다는 신호나 받는다는 신호 절차를 거치지 않고, 보내는 쪽에서 일방적으로 데이터를 전달하는 통신 프로토콜이다. 보내는 쪽에서는 받는 쪽이 데이터를 받았는지 받지 않았는지 확인할 수 없고, 또 확인할 필요도 없도록 만들어진 프로토콜을 말한다.

인터넷 아이콘을 누르는 것과 동시에 자동적으로 중앙컴퓨터 서버와 연결되어 정보를 보내는 쪽과 받는 쪽이 서로 의사소통을 할 수 있도록 설계된 통신 프로토콜인 TCP(transmission control protocol)와 상대되는 개념이다. 예를 들어 이메일을 주고받을 때 '수신 확인'을 통해 상대방이 메일을 읽었는지 읽지 않았는지를 알 수 있는 것은 송수신측이 서로 데이터를 주고받을 수 있기 때문이다. 이처럼 송수신측이 서로 데이터를 주고받는 방식이 TCP이고, 수신측이 데이터를 받는지 안받는지 상관없이 송신측에서 데이터만 전달하면 되는 방식이 UDP이다.UDP는 수신측과 접속 절차를 거치지 않고 송신측에서 일방적으로 데이터를 보내는 방식으로, 이러한 서비스를 무관계(無關係) 서비스라 하고, 이 무관계 서비스의 통신규약이 UDP이다.

따라서 UDP는 TCP와 달리 데이터의 수신에 대한 책임을 지지 않는다. 이는 송신자는 정보를 보냈지만, 정보가 수신자에게 제때에 도착했는지 또는 정보 내용이 서로 뒤바뀌었는지에 관해서 송신자는 상관할 필요가 없다는 말이다. 또 TCP보다 안정성 면에서는 떨어지지만, 속도는 훨씬 빠르다.

 

 

 

728x90