2015년 5월 10일 일요일

waitpid 에서 WIFSTOPPED 와 WIFCONTINUED 활성화.

Advanced Programming in the UNIX Environment 제 3판 책을 보다가,
waitpid 함수를 실행시킨 후,
waitpid 가 child process 의 상태를 반환할 때, 사용하는
WIFSTOPPED 와  WIFCONTINUED 의 기능을 어떻게 확인해 볼 수 있을까 궁금해졌는데,

waitpid(pid, &status, WUNTRACED | WCONTINUED) 와 같이
WUNTRACED 와 WCONTINUED 를 같이 설정해 주면 되네.


man wait 의 실행 페이지를 보니까
설명이 잘 되어 있다.

           $ ./a.out &
           Child PID is 32360
           [1] 32359
           $ kill -STOP 32360
           stopped by signal 19
           $ kill -CONT 32360
           continued
           $ kill -TERM 32360
           killed by signal 15


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
 
void error_handling( char * msg );
 
 
int main(int argc, char * argv[] )
{
    int status;
    pid_t pid;
    int i;
 
    if( ( pid = fork() ) < 0 )
    {
        error_handling( "fork() fail!" );
    }
    else if( pid == 0 ) // child
    {
        int j;
        printf("child self print : %d\n", getpid() );
 
 
        for( j=0; j < 100; j++ )
        {
            printf("child : %d\n", j );
            sleep(2);
            //status = status / 0;
            //abort();
            //pause();
        }
 
        return 3;
    }
    else
    {
        printf"child PID : %d\n", pid );
 
        do
        {
            if( waitpid(pid, &status, WUNTRACED | WCONTINUED)  != pid )
            {
                error_handling("wait() failed!");
            }
 
            if( WIFEXITED( status ) )
            {
                printf("child normal   termination : %d\n", WEXITSTATUS( status ) );
            }
            else if( WIFSIGNALED( status ) )
            {
                printf("child abnormal termination : %d, msg : '%s'\n",
                        WTERMSIG( status ),
                        strsignal( WTERMSIG( status ) )
                    );
            }
            else if( WIFSTOPPED( status ) )
            {
                printf("child stop : %d\n", WSTOPSIG( status ) );
            }
            else if( WIFCONTINUED( status ) )
            {
                printf("child continue\n" );
            }
        }while!WIFEXITED(status) && !WIFSIGNALED(status) );
        
    }
 
 
    return 0;
}
 
 
void error_handling( char * msg )
{
    fputs( msg, stderr );
    putc('\n', stderr );
 
    fprintf(stderr, "error number  : %d\n", errno );
    fprintf(stderr, "error message : %s\n", strerror( errno ) );
 
    exit(1);
 
}
cs

2015년 5월 3일 일요일

setsockopt 의 SO_SNDBUF 설정 후, 설정 값이 2 개가 되는 현상.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
 
 
void error_handle( char * msg);
 
int main(int argc, char * argv[] )
{
    int sock_tcp;
    int sock_udp;
 
    int option;
    socklen_t length; // sys/types.h
 
    sock_tcp = socket( PF_INET, SOCK_STREAM, 0 );
 
    if( sock_tcp == -1 )
        error_handle( "socket error()" );
 
    sock_udp = socket( PF_INET, SOCK_DGRAM, 0 );
 
    if( sock_udp == -1 )
        error_handle( "scoket error()" );
 
 
 
 
    length = sizeof( option );
    if( getsockopt( sock_tcp, SOL_SOCKET, SO_SNDBUF, (void*) &option, &length ) == -1 )
        error_handle( "getsockopt() error" );
 
    printf"tcp send    buffer size : %d\n", option );
 
    length = sizeof( option );
    if( getsockopt( sock_tcp, SOL_SOCKET, SO_RCVBUF, (void*) &option, &length ) == -1 )
        error_handle( "getsockopt() error" );
 
    printf"tcp receive buffer size : %d\n", option );
 
 
    option = 1024 * 10;
    if( setsockopt( sock_tcp, SOL_SOCKET, SO_SNDBUF, (void*) &option, sizeof( option ) ) == -1 )
        error_handle( "setsockopt() error" );
 
    length = sizeof( option );
    option = 1024 * 20;
    if( setsockopt( sock_tcp, SOL_SOCKET, SO_RCVBUF, (void*) &option, sizeof( option ) ) == -1 )
        error_handle( "setsockopt() error" );
 
 
    length = sizeof( option );
    if( getsockopt( sock_tcp, SOL_SOCKET, SO_SNDBUF, (void*) &option, &length ) == -1 )
        error_handle( "getsockopt() error" );
 
    printf"tcp send    buffer size : %d\n", option );
 
    length = sizeof( option );
    if( getsockopt( sock_tcp, SOL_SOCKET, SO_RCVBUF, (void*) &option, &length ) == -1 )
        error_handle( "getsockopt() error" );
 
    printf"tcp receive buffer size : %d\n", option );
 
 
    /*
    length = sizeof( option );
    if( getsockopt( sock_udp, SOL_SOCKET, SO_SNDBUF, (void*) &option, &length ) == -1 )
        error_handle( "getsockopt() error" );
    printf( "udp send    buffer size : %d\n", option );
    length = sizeof( option );
    if( getsockopt( sock_udp, SOL_SOCKET, SO_RCVBUF, (void*) &option, &length ) == -1 )
        error_handle( "getsockopt() error" );
    printf( "udp receive buffer size : %d\n", option );
    */
 
    close (sock_tcp);
    close (sock_udp);
 
    return 0;
}
 
 
void error_handle( char * msg )
{
    fprintf( stderr, "%s\n", msg );
    fprintf( stderr, "errno number : %d\n", errno );
    fprintf( stderr, "errno message: %s\n", strerror( errno ) );
    exit(1);
}
 
cs



위 코드의 결과.

tcp send    buffer size : 16384
tcp receive buffer size : 87380
tcp send    buffer size : 20480
tcp receive buffer size : 40960


실제
setsockopt 의 변수로, 10240 을 주면 그의 2 배인 20480,
setsockopt 의 변수로, 20480 을 주면 그의 2 배인 40960
이 나온다.

왜 그런지 확인해 보려면,

man 7 socket
명령어를 linux 에서 실행시켜 보면,

아래와 같은 안내를 볼 수 있다.

       SO_SNDBUF
              Sets  or gets the maximum socket send buffer in bytes.  The kernel doubles this value (to allow space for
              bookkeeping overhead) when it is set using setsockopt(2), and this doubled value is returned by  getsock‐
              opt(2).   The  default  value  is set by the /proc/sys/net/core/wmem_default file and the maximum allowed
              value is set by the /proc/sys/net/core/wmem_max file.  The minimum (doubled) value  for  this  option  is
              2048.



UDP와 TCP 소켓의 SND/RCV 버퍼 크기 보기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
void error_handle( char * msg);
int main(int argc, char * argv[] )
{
    int sock_tcp;
    int sock_udp;
    int option;
    socklen_t length; // sys/types.h
    sock_tcp = socket( PF_INET, SOCK_STREAM, 0 );
    if( sock_tcp == -1 )
        error_handle( "socket error()" );
    sock_udp = socket( PF_INET, SOCK_DGRAM, 0 );
    if( sock_udp == -1 )
        error_handle( "scoket error()" );
    length = sizeof( option );
    if( getsockopt( sock_tcp, SOL_SOCKET, SO_SNDBUF, (void*) &option, &length ) == -1 )
        error_handle( "getsockopt() error" );
    printf"tcp send    buffer size : %d\n", option );
    length = sizeof( option );
    if( getsockopt( sock_tcp, SOL_SOCKET, SO_RCVBUF, (void*) &option, &length ) == -1 )
        error_handle( "getsockopt() error" );
    printf"tcp receive buffer size : %d\n", option );
    length = sizeof( option );
    if( getsockopt( sock_udp, SOL_SOCKET, SO_SNDBUF, (void*) &option, &length ) == -1 )
        error_handle( "getsockopt() error" );
    printf"udp send    buffer size : %d\n", option );
    length = sizeof( option );
    if( getsockopt( sock_udp, SOL_SOCKET, SO_RCVBUF, (void*) &option, &length ) == -1 )
        error_handle( "getsockopt() error" );
    printf"udp receive buffer size : %d\n", option );
    close (sock_tcp);
    close (sock_udp);
    return 0;
}
void error_handle( char * msg )
{
    fprintf( stderr, "%s\n", msg );
    fprintf( stderr, "errno number : %d\n", errno );
    fprintf( stderr, "errno message: %s\n", strerror( errno ) );
    exit(1);
}


위와 같은 코드를 사용해서,
UDP와 TCP 소켓의 send buffer 와 receive buffer 크기를 살펴보니,
기본적으로 다르게 설정되어 있음을 알았다.


이를 실행하면,

tcp send buffer size : 16384
tcp receive buffer size : 87380
udp send buffer size : 112640
udp receive buffer size : 112640
이 나왔다.

Linux 에서 기본 설정하는 TCP SND/RCV 버퍼 크기는
sysctl -n net.ipv4.tcp_wmem ( SND 크기 )
sysctl -n net.ipv4.tcp_rmem ( RCV 크기 )
명령어로 확인할 수 있다.


UDP 의 경우 아래로 확인하면 될 것 같다.
sysctl -n net.core.wmem_default sysctl -n net.core.rmem_default


https://wwwx.cs.unc.edu/~sparkst/howto/network_tuning.php

cs

팔로어