No silver Bullet

Posted at 2010/04/22 10:14 // in Programming // by Daniel
The Mythical Man-month에 나온 이야기
유명한 페이퍼입니다.

소프트웨어 개발에 하나의 방법으로 모든 도메인에 일정과 품질을 향상시키는 "마법의 탄환"은 없다는거죠 :-)
pdf 출처는 http://people.eecs.ku.edu/~saiedian/Teaching/Sp08/816/Papers/Background-Papers/no-silver-bullet.pdf 입니다. 구글검색 :-)

크리에이티브 커먼즈 라이센스
Creative Commons License

간단한 FIFO queue 예제

Posted at 2010/04/22 08:35 // in Programming // by Daniel

#include <stdio.h>

static char qout( void );
static int qin( char in );
static int  qlen ( void );
#define Q_MAX   4
int queue[Q_MAX];
int qhead=0;
int qtail=0;
int main(void)
{
    char io;
    char input;
    int exit=0;
    int state=0;
    char rd;
    printf("simple queue test\n");
    fflush(stdin);
    do {
        switch(state) {
            case 0:
                printf("cmd $ ");
                state = 1;
            case 1:
                fflush(stdout);
                fflush(stdin);
                rd = getchar();
                if (rd==' ' || rd=='\n')
                    continue;
                if (rd=='q') {
                    exit=1;
                    break;
                }
                // get cmd;
                if (rd=='i')
                    state = 5;
                if (rd=='o')
                    state = 10;
                break;
            case 5:
                // input
                printf("input$ ");
                state = 6;
            case 6:
                fflush(stdout);
                fflush(stdin);
                rd = getchar();
                if (rd==' ' || rd=='\n')
                    continue;
                if (rd=='q') {
                    exit=1;
                    break;
                }
                input = rd;
                qin(input);
                printf("h=%d, tail=%d qlen=%d\n", qhead, qtail, qlen());
                state = 0;
                break;
            case 10:
                // get

                printf("%c\n", qout());
                printf("h=%d, tail=%d qlen=%d\n", qhead, qtail, qlen());
                state = 0;
                break;
            default:
                printf("default state??\n");
                exit=1;
        } // switch
    } while(!exit);

    return 0;
}

static int  qlen ( void )
{
    if ( qhead >= qtail )
        return qhead-qtail;
    return qhead+Q_MAX+1-qtail;
}

static int qin( char in )
{
    int tmp_head = qhead;
    tmp_head++;
    if (tmp_head==(Q_MAX+1))
        tmp_head=0;
    if (tmp_head==qtail) {
        // overrun
        fprintf(stderr, "q overrun\n");
        return -1;
    }
    printf("q[%d]<:=%c\n", qhead, in);
    queue[qhead] = in;
    qhead = tmp_head;
    return 0;
}

static char qout( void )
{
    int tmp_tail = qtail;
    if (qtail == qhead) {
        // underrun
        fprintf(stderr, "q underrun\n");
        return '\b';
    }
    qtail = (tmp_tail +1 );
    if (qtail == (Q_MAX+1))
        qtail = 0;
    printf("q[%d]==%c\n", tmp_tail, queue[tmp_tail]);
    return queue[tmp_tail];
}

리팩토링 필요 – 리팩토링 했지만 여기에 게시하진 않음.
크리에이티브 커먼즈 라이센스
Creative Commons License

소프트웨어 크리에이티비티 2.0

Posted at 2009/05/25 14:47 // in Programming // by Daniel

http://jhrogue.blogspot.com/2009/05/20.html

소개받은책.

살까나

크리에이티브 커먼즈 라이센스
Creative Commons License

함수의 리턴 주소 알아내기

Posted at 2009/03/23 11:16 // in Programming // by Daniel

프로파일링이나 함수 래핑으로 lock등의 작업을 가로채서 로깅할 때 호출한 쪽의 PC값을 알고 싶을 경우가 있습니다.

현재실행되는 함수 입장에서 보면 리턴 주소이죠

이 때 쓸 수 있는 함수가 gcc의 builtin함수로 __builtin_return_address() 입니다.

__builtin_return_address(level)

여기서 level은 call stack 에서 몇번째를 리턴할 것인지에 대한 값입니다.

__builtin_return_address(0) 하면 현재함수의 리턴주소가 나옵니다.

__builtin_return_address(1) 하면 나를 호출한 함수의 리턴주소가 나옵니다...

예제 코드를 짜봤습니다.

#include <stdio.h>
#include <stdlib.h>

int my_func1()
{
    void *addr;
    addr = __builtin_return_address(0);
    printf("1's caller %p\n",addr);
    printf("hello 1\n");
}
int my_func0()
{
    void *addr;
    printf("hello 0\n");
    addr = __builtin_return_address(0);
    printf("0's caller %p\n",addr);
    my_func1();
}

int main(void)
{
    printf("backtrace test\n");
    printf("main: %p\n", (void *)main);
    printf("my_func0: %p\n", (void *)my_func0);
    printf("my_func1: %p\n", (void *)my_func1);
    my_func0();
    return 0;
}


이 소스코드를 컴파일해서 objdump해보면

080483d1 <my_func0>:
...
80483fc:   e8 a3 ff ff ff          call   80483a4 <my_func1>
8048401:   c9                      leave
8048402:   c3                      ret

08048403 <main>:
...

804845c:   e8 70 ff ff ff          call   80483d1 <my_func0>
8048461:   b8 00 00 00 00          mov    $0x0,%eax
...

이와 같이 호출하게 되어있고

실행해보면

backtrace test
main: 0x8048403
my_func0: 0x80483d1
my_func1: 0x80483a4
hello 0
0's caller 0x8048461
1's caller 0x8048401
hello 1

이렇게 나옵니다. call 바로 다음 주소--리턴 주소가 나오지요.

이외에도 몇가지 builtin함수들이 있습니다.

예를 들어 __builtin_frame_address(level)은 프레임 포인터를 반환합니다.


관련 포스트 :

gcc 컴파일 옵션으로 커스텀 프로파일 해서 실행 트레이스 뽑기

크리에이티브 커먼즈 라이센스
Creative Commons License

코드에서 glibc 버전 알아내기

Posted at 2008/08/21 21:19 // in Programming // by Daniel

http://www.technovelty.org/linux/tips/glibc-version.html

실행중에 libc 버전을 봐야 할 경우, contstr을 쓰면 된다고 합니다

#include <stdio.h>

#include <unistd.h>

#include <alloca.h>

#include <string.h>


int main (void)

{

    size_t n = confstr (_CS_GNU_LIBC_VERSION, NULL, 0);

    if (n > 0)

    {

        char *buf = alloca (n);

        confstr (_CS_GNU_LIBC_VERSION, buf, n);

        printf("%s\n", buf);

    }

    return 0;

}

 

실행해 보면
 $ ./a.out
glibc 2.7

이렇게 나옵니다.
또는 돌리는 코드상에서가 아니고 콘솔에서 보고 싶다면 /lib/libc.so.6 파일을 실행해봐도 됩니다.
$ /lib/libc.so.6
GNU C Library stable release version 2.7, by Roland McGrath et al.
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.2.3 (Ubuntu 4.2.3-2ubuntu7).
Compiled on a Linux >>2.6.24-14-server<< system on 2008-04-04.
Available extensions:
    crypt add-on version 2.1 by Michael Glad and others
    GNU Libidn by Simon Josefsson
    Native POSIX Threads Library by Ulrich Drepper et al
    BIND-8.2.3-T5B
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.

그리고 LD_DEBUG를 이용하면 많은 정보를 볼 수 있습니다.

$ LD_DEBUG=help ls
Valid options for the LD_DEBUG environment variable are:

  libs        display library search paths
  reloc       display relocation processing
  files       display progress for input file
  symbols     display symbol table processing
  bindings    display information about symbol binding
  versions    display version dependencies
  all         all previous options combined
  statistics  display relocation statistics
  unused      determined unused DSOs
  help        display this help message and exit

To direct the debugging output into a file instead of standard output
a filename can be specified using the LD_DEBUG_OUTPUT environment variable.


예를 들어 아까의 a.out을 실행하면

$ LD_DEBUG=versions ./a.out
      1565:     checking for version `GLIBC_2.4' in file /lib/tls/i686/cmov/libc.so.6 [0] required by file ./a.out [0]
      1565:     checking for version `GLIBC_2.0' in file /lib/tls/i686/cmov/libc.so.6 [0] required by file ./a.out [0]
      1565:     checking for version `GLIBC_PRIVATE' in file /lib/ld-linux.so.2 [0] required by file /lib/tls/i686/cmov/libc.so.6 [0]
      1565:     checking for version `GLIBC_2.3' in file /lib/ld-linux.so.2 [0] required by file /lib/tls/i686/cmov/libc.so.6 [0]
      1565:     checking for version `GLIBC_2.1' in file /lib/ld-linux.so.2 [0] required by file /lib/tls/i686/cmov/libc.so.6 [0]
      1565:
      1565:     calling init: /lib/tls/i686/cmov/libc.so.6
      1565:
      1565:
      1565:     initialize program: ./a.out
      1565:
      1565:
      1565:     transferring control: ./a.out
      1565:
glibc 2.7
      1565:
      1565:     calling fini: ./a.out [0]
      1565:
      1565:
      1565:     calling fini: /lib/tls/i686/cmov/libc.so.6 [0]
      1565:

이런 식으로 나옵니다.
크리에이티브 커먼즈 라이센스
Creative Commons License