• 리눅스 vs. 윈도우
    : 편견을 갖을 필요 없다. 각각의 장단점이 있다.
    : 시스템콜 기반과 표준라이브러리 IO와 차이
    : 시스템콜 메커니즘 자체는 리눅스와 윈도우가 같다.

    : 리눅스는 무료 오픈소스로 파일 디스크립터, 오픈파일 등의 세팅을 바꾸어줄수 있지만 윈도우즈는 변경하기가 힘들고, 가격이 비싸지만 (windows server 같은 경우 cpu당 라이센스 비용 지불), 개발이 쉽다.
    : 바로 함수를 호출하는 메커니즘 vs 하나를 거쳐 호출하는 메커니즘
    : mono vs micro
    : 커널을 다시 빌드해야함 vs 모듈처럼 사용 가능하지만 성능 저하
    : android 코드를 분석해보면 bionic -> 각각의 CPU에 대해 존재하는 이유는 시스템콜 때문이다.



  • 시스템 콜

    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    #include <stdio.h >
    
    // stdin, stdout, stderr : FILE*
    // STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO : int
    
    // task_struct
    
    // 1. socket programming 저수준 IO를 사용합니다.
    // 2. 저수준 IO : 운영체제에서 제공하는 IO 관련 API
    //   Windows : Win32/64 API
    //   Linux   : System Call
    
    // 3. 프로세스를 통해 파일을 관리한다.
    //   ulimit -a
    
    int main()
    {
    	// FILE* fp = fopen("sample", "r");
    	int fd = open("sample", O_RDONLY);
    
    	printf("fd : %d\n", STDIN_FILENO);
    	printf("fd : %d\n", STDOUT_FILENO);
    	printf("fd : %d\n", STDERR_FILENO);
    	printf("fd : %d\n", fd);
            // fd 출력시 3인 이유는 표준 입출력, 에러에 대한 fd가 열려있기 때문이다
            // VFS라고 부른다 -> 다형성
            // 내부적으로 파일, 디바이스를 다루는 모든 방식은 파일로 되어있다. 이를 사용하기 위해서는 각각을 모두 열어야한다. -> 동적바인딩을 통해서
            // 리눅스는 array로 파일디스크립터 관리, 윈도우즈는 파일디스크립터 핸들
    }
    

    버퍼링 정책 3가지

     1. Full Buffering : Buffer가 가득 차면 화면에 출력    → File I/O
     2. Line Buffering : ‘\n’이 오면 화면에 출력          → printf의 경우에 해당
     3. Non Bufering : 버퍼링을 하지 않음.              → fprintf(stderr,””);에 해당

      pirntf("error");

      while(1); 

      //출력하지 않는다.


      pirntf("error\n");

      while(1); 

      //출력한다.

    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    #include <stdio.h>
    
    int main()
    {
    	int fd = open("sample", O_RDONLY);
    	printf("fd : %d\n", fd);
    
    
    	// 문제점 
    	// 1. 에러 발생시 -1 리턴
    	// 2. 버퍼의 크기가 너무 작을 경우, 빈번한 컨텍스트 스위칭으로 인한
    	//    성능 저하가 있다.
    #if 0
    	char ch;
    	while (read(fd, &ch, sizeof ch) > 0)
    		putchar(ch);
    #endif
    
    	// 3. read(fd, buf, size)
    	//	size : 버퍼의 최대 크기
    	// 4. write(fd, buf, size)
    	//  size : 쓰고자 하는 데이터의 실제 양
    
    	char buf[128];
    	int ret;
    	while ((ret = read(fd, buf, sizeof buf)) > 0) {
    		write(1, buf, ret);
    
    		// buf[ret] = '\0';
    		// printf("%s", buf);
    	}
    
    	close(fd);
            // close를 안해도 문제가 없었던 이유
            // 프로세스가 종료되면서 소유하고 있던 자원을 모두 해지
    
            // app영역에서는 프로세스 종료로 OS가 메모리를 수거함. 대부분 커널의 누수
            // 정적분석은 new와 delete쌍을 찾아서 싱글톤은 메모리 누수로 인식함
            // 동적분석은 비쌈
    
    }
    
    
    
    
    


  • 클라이언트 작성하기
    - http 통신

    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    #include <errno.h>
    #include <string.h>
    
    int main()
    {
    	// 1. 소켓 생성 : socket()
    	int sd = socket(PF_INET,      //  프로토콜
    									SOCK_STREAM,  //  TCP(SOCK_STREAM), UDP(SOCK_DGRAM)
    									IPPROTO_TCP); //  하위 프로토콜(생략, 0 으로 지정 가능)
    	
    	// 2. 서버 주소 지정 : 초기화 이전에 0으로 초기화해야 한다.
    	// 문자열 ip -> 32 bit : inet_addr
    	struct sockaddr_in addr = {0, };
    	addr.sin_family = AF_INET; 
    	addr.sin_port = htons(80);
    	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    	// 3. 접속 수행 
    	int ret = connect(sd, (struct sockaddr*)&addr, sizeof(addr)); 
    	if (ret == -1) {
    		// 에러 처리 방법 3가지
    		// 1. printf("connect() error : %d\n", errno);
    
    		// 2. char* msg = strerror(errno);
    		//    printf("connect() error : %s\n", msg);
    		
    		// 3.
    		perror("connect()");
    		goto err;
    	}
    
    	{
    		printf("Connection succeed!!\n");
    
    		// "GET \n\n"
    		char buf[1024] = "GET /\n\n";
    		write(sd, buf, strlen(buf));
    
    		int len;
    		while ((len = read(sd, buf, sizeof(buf))) > 0) {
    			write(1, buf, len);
    		}
    	}
    
    err:
    	// 4. 접속 종료
    	close(sd);
    }


    - DNS

    #include <stdio.h>
    // domain -> ip address
    // : gethostbyname
    
    // gethostbyname
    #include <netdb.h>    
    
    // inet_ntoa: 네트워크로부터 온 패킷을 아스키코드로 바꾸어 주는 것
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    int main()
    {
    	struct hostent* host = gethostbyname("www.google.com");
    
    	// name
    	printf("host name : %s\n", host->h_name);
    
    	// alias
    	for (int i = 0 ; host->h_aliases[i] ; i++) {
    		printf("Alias[%d] : %s\n", i + 1, host->h_aliases[i]);
    	}
    
    	for (int i = 0 ; host->h_addr_list[i] ; i++) {
    		printf("Address[%d] : %s\n", 
    				i+1,
    				inet_ntoa(*(struct in_addr*)host->h_addr_list[i]) );
    	}
    }
    


+ Recent posts