Linux API/network2009. 6. 23. 00:50
fork()는 리눅스 시스템 콜로서, 프로세스를 생성한다.

#include "stdio.h"
#include "unistd.h"

int main() { pid_t pid; pid = fork();
switch( pid) { case -1: // fail case 0: // child default: // parent break; } }
개략적인 코드는 위와 같은데,
왜! switch 문데 child와 parent가 동시에 들어가는지에 대해서 생각을 해보도록 하자.

일단 fork() + exec() 의 조합으로 쓰게 되는데,
fork()는 프로세스를 생성하고, exec()는 프로그램을 바꾸어서 실행하는 역활을 한다.
다시 앞을 자세히 보자.

프로세스를 생성한다.

어려운 이야기를 제외하고, 프로세스는 메모리상에 올라와있는(적재되어 있는, 혹은 메모리에 load된)
프로그램으로, 프로세스를 생성하는 가장 편한 방법은 복사이다.
현재 수행중인 프로세스의 내용을 그대로 복사해서 다른 pid를 준다.
그게 바로 fork 이고, 위의 switch문을 이해할 수 있는 키가 된다.

굳이 비유를 하자면, 예전에 일요일에 했던 이휘재가 그래 결정했어! 를 외치던 그 프로그램을 떠올려 보자.
어느 시점에서 그대로 복제한 메모리의 정보가 생성이 되었고
그 분기점에서 어느길을 택할지를 결정하여 주면, 각각의 프로그램이 따로 돌아가게 된다.


즉, 복사한 시점에서 표지판 역활을 해주는 것이
fork()의 리턴값인 pid_t 형의 pid 이고,
이 값이 어느 쪽으로 분기되어 갈지를 결정하게 해주는 것이다.

그런 이유로, Parent, Child 의 코드가 하나의 소스에 들어 있게 되고
별거 아닌 것 같지만, 상당히 헷갈리는(왜 코드가 하나에 들어 있지?) 이유가 된다.

[링크 : http://linux.die.net/man/2/fork]

'Linux API > network' 카테고리의 다른 글

Linux File Descriptor / File pointer  (0) 2009.06.30
getline()  (0) 2009.06.25
signal / kill / raise  (0) 2009.06.21
flock - apply or remove an advisory lock on an open file  (0) 2009.06.20
네트워크 장치 갯수 얻기 (get amount of eth?)  (0) 2009.06.18
Posted by 구차니
Linux API/network2009. 6. 21. 13:04
signal - ANSI C signal handling
kill - send signal to a process
raise - send a signal to the current process

signal()은 시그널 핸들러를 등록하고
 #include <signal.h>
 sighandler_t signal(int signum, sighandler_t handler);

kill은 시그널 을 전송하고
 #include <sys/types.h>
 #include <signal.h>
 int kill(pid_t pid, int sig);

raise는 자기자신에게 시그널을 전송한다.
 #include <signal.h>
 int raise(int sig);
 kill(getpid(), sig);

아무래도, pid 단위로 시그널을 전송함으로서 제어에 상당한 제약이 있을것으로 보인다.
그리고 쓰레드는 2.5 커널 이상 부터는 pid가 동일하게 나온다고 한다.
[링크 : http://kldp.org/node/35609]

*** man page ***
[signal(2) : http://linux.die.net/man/2/signal]
[kill(2) : http://linux.die.net/man/2/kill]
[raise(2) : http://linux.die.net/man/3/raise]

*** joinc wiki ***
시그널 처리하기
시그널 사용하기 1
시그널 사용하기 2
리눅스 시스템 프로그래밍 6장 시그널

'Linux API > network' 카테고리의 다른 글

getline()  (0) 2009.06.25
fork에 관한 짧은 이야기  (2) 2009.06.23
flock - apply or remove an advisory lock on an open file  (0) 2009.06.20
네트워크 장치 갯수 얻기 (get amount of eth?)  (0) 2009.06.18
gateway 정보  (0) 2009.06.05
Posted by 구차니
Linux API/network2009. 6. 20. 18:55
flock은 이름대로 파일 디스크립터를 lock 하거나 unlock 하는데 사용한다.
멀티 유저/ 멀티 프로세스 OS인 관계로 Linux/Unix에서는 열린 파일도 여러사람이 또 열어서 쓸 수 있는데
다르게 말하자면 시리얼 포트 역시 동시에 여러사람이 열어서 사용이 가능하다는 의미이다.

하지만, 시리얼 포트를 동시에 여러 사람이 열어서 사용하다 보면 문제가 발생할 수도 있기에
(내용이 서로 엇갈린다던가) 특정 시기에 대해서는 타인이 사용하지 못하도록 배타적으로 잠궈야 할 때도 있다.

int flock(int fd, int operation);

    LOCK_SH
        Place a shared lock. More than one process may hold a shared lock for a given file at a given time.

    LOCK_EX
        Place an exclusive lock. Only one process may hold an exclusive lock for a given file at a given time.

    LOCK_UN
        Remove an existing lock held by this process.

[링크 : http://linux.die.net/man/2/flock]

LOCK_EX로 하면 자기만 쓸 수 있도록 잠그는 것이고,
LOCK_UN으로 잠금을 해제 한다.



[링크 : http://feedtome.springnote.com/pages/141729]
[링크 : http://stackoverflow.com/questions/691676/getting-exclusive-access-to-a-tty-device-from-a-root-program-on-linux]

'Linux API > network' 카테고리의 다른 글

fork에 관한 짧은 이야기  (2) 2009.06.23
signal / kill / raise  (0) 2009.06.21
네트워크 장치 갯수 얻기 (get amount of eth?)  (0) 2009.06.18
gateway 정보  (0) 2009.06.05
linux에서 ip/mac address 받아오기 관련 링크  (0) 2009.06.05
Posted by 구차니
Linux API/network2009. 6. 18. 21:19
아래의 소스에서 눈여겨 볼 부분은 다음과 같다.
    struct ifreq *ifr;
    struct ifconf ifcfg;

    ioctl(fd, SIOCGIFCONF, (char *)&ifcfg);

    // 네트워크 장치의 정보를 얻어온다. 
    // 보통 루프백과 하나의 이더넷 카드를 가지고 있을 것이므로
    // 2개의 정보를 출력할 것이다.

    ifr = ifcfg.ifc_req;
    for (n = 0; n < ifcfg.ifc_len; n+= sizeof(struct ifreq))
    {
        // 주소값을 출력하고 루프백 주소인지 확인한다.
        printf("[%s]\n", ifr->ifr_name);
        sin = (struct sockaddr_in *)&ifr->ifr_addr;
        printf("IP    %s %d\n", inet_ntoa(sin->sin_addr), sin->sin_addr.s_addr);
        if ( ntohl(sin->sin_addr.s_addr) == INADDR_LOOPBACK)
        {
            printf("Loop Back\n");
        }
        else
        {
            // 루프백장치가 아니라면 MAC을 출력한다.
        }
        ifr++;
    }

ifr은 struct ifreq인데, 여러개가 있을 수 있으니, 저런식으로 포인터로 증가를 시켜준다. (ifr++)
그리고 n개의 네트워크 장치가 있을 수 있으니, ifcfg.ifc_len의 값으로 전체 갯수를 알려준다.
그 다음에는 장치명(익숙한 eth0 라던가)은 ifr->ifr_name에 들어있다.

#include "sys/ioctl.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "sys/socket.h"
#include "unistd.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "net/if.h"
#include "arpa/inet.h"

int main()
{
    // 이더넷 데이터 구조체 
    struct ifreq *ifr;
    struct sockaddr_in *sin;
    struct sockaddr *sa;

    // 이더넷 설정 구조체
    struct ifconf ifcfg;
    int fd;
    int n;
    int numreqs = 30;
    fd = socket(AF_INET, SOCK_DGRAM, 0);

    // 이더넷 설정정보를 가지고오기 위해서 
    // 설정 구조체를 초기화하고  
    // ifreq데이터는 ifc_buf에 저장되며, 
    // 네트워크 장치가 여러개 있을 수 있으므로 크기를 충분히 잡아주어야 한다.  
    // 보통은 루프백주소와 하나의 이더넷카드, 2개의 장치를 가진다.
    memset(&ifcfg, 0, sizeof(ifcfg));
    ifcfg.ifc_buf = NULL;
    ifcfg.ifc_len = sizeof(struct ifreq) * numreqs;
    ifcfg.ifc_buf = malloc(ifcfg.ifc_len);

    for(;;)
    {
        ifcfg.ifc_len = sizeof(struct ifreq) * numreqs;
        ifcfg.ifc_buf = realloc(ifcfg.ifc_buf, ifcfg.ifc_len);
        if (ioctl(fd, SIOCGIFCONF, (char *)&ifcfg) < 0)
        {
            perror("SIOCGIFCONF ");
            exit;
        }
        // 디버깅 메시지 ifcfg.ifc_len/sizeof(struct ifreq)로 네트워크 
        // 장치의 수를 계산할 수 있다.  
        // 물론 ioctl을 통해서도 구할 수 있는데 그건 각자 해보기 바란다.
        printf("%d : %d \n", ifcfg.ifc_len, sizeof(struct ifreq));
        break;
    }

    // 주소를 비교해 보자.. ifcfg.if_req는 ifcfg.ifc_buf를 가리키고 있음을 
    // 알 수 있다. 
    printf("address %d\n", &ifcfg.ifc_req);
    printf("address %d\n", &ifcfg.ifc_buf);

    // 네트워크 장치의 정보를 얻어온다.  
    // 보통 루프백과 하나의 이더넷 카드를 가지고 있을 것이므로 
    // 2개의 정보를 출력할 것이다. 
    ifr = ifcfg.ifc_req;
    for (n = 0; n < ifcfg.ifc_len; n+= sizeof(struct ifreq))
    {
        // 주소값을 출력하고 루프백 주소인지 확인한다.
        printf("[%s]\n", ifr->ifr_name);
        sin = (struct sockaddr_in *)&ifr->ifr_addr;
        printf("IP    %s %d\n", inet_ntoa(sin->sin_addr), sin->sin_addr.s_addr);
        if ( ntohl(sin->sin_addr.s_addr) == INADDR_LOOPBACK)
        {
            printf("Loop Back\n");
        }
        else
        {
            // 루프백장치가 아니라면 MAC을 출력한다.
            ioctl(fd, SIOCGIFHWADDR, (char *)ifr);
            sa = &ifr->ifr_hwaddr;
            printf("%s\n", ether_ntoa((struct ether_addr *)sa->sa_data));
        }
        // 브로드 캐스팅 주소 
        ioctl(fd,  SIOCGIFBRDADDR, (char *)ifr);
        sin = (struct sockaddr_in *)&ifr->ifr_broadaddr;
        printf("BROD  %s\n", inet_ntoa(sin->sin_addr));
        // 네트워크 마스팅 주소
        ioctl(fd, SIOCGIFNETMASK, (char *)ifr);
        sin = (struct sockaddr_in *)&ifr->ifr_addr;
        printf("MASK  %s\n", inet_ntoa(sin->sin_addr));
        // MTU값
        ioctl(fd, SIOCGIFMTU, (char *)ifr);
        printf("MTU   %d\n", ifr->ifr_mtu);
        printf("\n");
        ifr++;
    }
}

[링크 : http://www.joinc.co.kr/modules.php?file=article&mode=nested&name=News&sid=148]
Posted by 구차니
Linux API/usb2009. 6. 8. 20:27
증상 : USB hotplug 및 인식/사용에 아무런 이상없으나, /proc/bus/usb 에 아무런 파일 없음

mount -t usbfs usbfs /proc/bus/usb/
를 실행해주면 해결된다.

[링크 : http://www.linuxquestions.org/.../cannot-open-procbususbdevices-no-such-file-or-directory-378916/]


다른 링크에 의하면 ACPI 문제라던가, 커널 설정상의 문제가 있을 가능성이 있다고 한다.
[링크 : http://www.linuxquestions.org/.../mdk-10.2-no-usb-at-all-procbususbdevices-missing-326350/]

---
2012.02.04 추가

우분투에서 하니 usbfs로 마운트가 되지 않고 /proc/bus/usb 를 찾을 수 없다는 에러만 나타낸다.
그래서 mkdir로 생성해주려고 해도 배째는데, 아래와 같이 ln 으로 연결해주니 된다!!
대신 기존의 /proc/bus 는 통채로 사라지니 주의해야 한다.
차라리 /sys/kernel/debug/usb/devices 를 들어가서 보는게 나을지도 모르겠다.
$ sudo mount --bind /dev/bus /proc/bus
$ sudo ln -s /sys/kernel/debug/usb/devices /proc/bus/usb/devices   

[링크 : http://ubuntuforums.org/showthread.php?t=1648118 ] 



'Linux API > usb' 카테고리의 다른 글

usbfs / usb api  (0) 2012.02.04
usb 버스 정보 얻기  (0) 2009.06.08
Posted by 구차니
Linux API/usb2009. 6. 8. 17:47
/proc/bus/usb/devices 를 읽으면 되는데
보기가 힘들다.


이걸 쉽게 보려면
usbtree 라는 perl 스크립트를 http://www.linux-usb.org/usb2.html 페이지에서 받아서 사용하면된다.

/: Bus 05.Port 1: Dev 1, Class=root_hub, Drv=ehci_hcd/8p, 480M
    |_ Port 1: Dev 7, If 0, Prod=ST3250310AS, Class=stor., Drv=usb-storage, 480M
    |_ Port 2: Dev 6, If 0, Prod=SKYMIRROR, Class=stor., Drv=usb-storage, 480M
/: Bus 04.Port 1: Dev 1, Class=root_hub, Drv=uhci_hcd/2p, 12M
/: Bus 03.Port 1: Dev 1, Class=root_hub, Drv=uhci_hcd/2p, 12M
/: Bus 02.Port 1: Dev 1, Class=root_hub, Drv=uhci_hcd/2p, 12M
    |_ Port 1: Dev 2, If 0, Prod=USB Optical Mouse, Class=HID, Drv=usbhid, 1.5M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Drv=uhci_hcd/2p, 12M

내용을 보니 그래도 버스 순서대로 출력이 되는 듯 하다.

'Linux API > usb' 카테고리의 다른 글

usbfs / usb api  (0) 2012.02.04
/proc/bus/usb 의 내용이 없을 경우(There is no files /proc/bus/usb)  (0) 2009.06.08
Posted by 구차니
Linux API/network2009. 6. 5. 19:33
$ more /proc/net/route
Iface   Destination     Gateway         Flags   RefCnt  Use     Metric  Mask            MTU     Window  IRTT
eth0    000AA8C0        00000000        0001    0       0       0       00FFFFFF        0       0       0
eth0    0000FEA9        00000000        0001    0       0       0       0000FFFF        0       0       0
eth0    00000000        010AA8C0        0003    0       0       0       00000000        0       0       0

$ netstat -nr
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
192.168.10.0    0.0.0.0         255.255.255.0   U         0 0          0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U         0 0          0 eth0
0.0.0.0         192.168.10.1    0.0.0.0         UG        0 0          0 eth0


0x010AA8C0 이 gateway인데 숫자가 뒤집혀 있다.
0x01. 0x0A. 0xA8. 0xC0
1.      10.     168.   192
Posted by 구차니
Linux API/network2009. 6. 5. 18:01

'Linux API > network' 카테고리의 다른 글

네트워크 장치 갯수 얻기 (get amount of eth?)  (0) 2009.06.18
gateway 정보  (0) 2009.06.05
network 관련 include 할 파일 목록  (0) 2009.06.05
offsetof() - stddef.h  (0) 2009.06.05
SIOCGIF가 모야?  (0) 2009.06.05
Posted by 구차니
Linux API/network2009. 6. 5. 17:55
#include <net/if.h>
struct ifreq

#include <netinet/in.h>
struct sockaddr_in

#include <sys/socket.h>
struct sockaddr

#include <netpacket/packet.h>
struct packet_mreq

#include <net/route.h>
struct rtentry

#include <netdb.h>
struct hostent
struct addrinfo


sockaddr의 경우 원본은 bits/socket.h에 있으나
sys/socket.h 에서 include 함으로 굳이 bits/socket.h를 include 할 필요는 없다.

'Linux API > network' 카테고리의 다른 글

gateway 정보  (0) 2009.06.05
linux에서 ip/mac address 받아오기 관련 링크  (0) 2009.06.05
offsetof() - stddef.h  (0) 2009.06.05
SIOCGIF가 모야?  (0) 2009.06.05
C언어로 MAC 어드레스 받아오기 (Linux)  (1) 2009.06.04
Posted by 구차니
Linux API/network2009. 6. 5. 16:03
ifconfig.c를 들여다 보고 있자니 신기한 녀석들이 나타나시었다.

struct arg1opt {
    const char *name;
    unsigned short selector;
    unsigned short ifr_offset;
};

#define ifreq_offsetof(x)  offsetof(struct ifreq, x)

static const struct arg1opt Arg1Opt[] = {
    {"SIOCSIFMETRIC",  SIOCSIFMETRIC,  ifreq_offsetof(ifr_metric)},
    {"SIOCSIFMTU",     SIOCSIFMTU,     ifreq_offsetof(ifr_mtu)},
    {"SIOCSIFTXQLEN",  SIOCSIFTXQLEN,  ifreq_offsetof(ifr_qlen)},
    {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)},
    {"SIOCSIFNETMASK", SIOCSIFNETMASK, ifreq_offsetof(ifr_netmask)},
    {"SIOCSIFBRDADDR", SIOCSIFBRDADDR, ifreq_offsetof(ifr_broadaddr)},
#ifdef BB_FEATURE_IFCONFIG_HW
    {"SIOCSIFHWADDR",  SIOCSIFHWADDR,  ifreq_offsetof(ifr_hwaddr)},
#endif
    {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)},
#ifdef SIOCSKEEPALIVE
    {"SIOCSKEEPALIVE", SIOCSKEEPALIVE, ifreq_offsetof(ifr_data)},
#endif
#ifdef SIOCSOUTFILL
    {"SIOCSOUTFILL",   SIOCSOUTFILL,   ifreq_offsetof(ifr_data)},
#endif
#ifdef BB_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
    {"SIOCSIFMAP",     SIOCSIFMAP,     ifreq_offsetof(ifr_map.mem_start)},
    {"SIOCSIFMAP",     SIOCSIFMAP,     ifreq_offsetof(ifr_map.base_addr)},
    {"SIOCSIFMAP",     SIOCSIFMAP,     ifreq_offsetof(ifr_map.irq)},
#endif
    /* Last entry if for unmatched (possibly hostname) arg. */
    {"SIOCSIFADDR",    SIOCSIFADDR,    ifreq_offsetof(ifr_addr)},
};

$ man offsetof
#include <stddef.h>
size_t offsetof(type, member);

머. 매크로로 해도 될텐데 왜 굳이 함수형으로 했을까는 조금 의문이지만,
간단하게 표현하자면 . 연산자를 붙여주는 역활을 한다.

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

       int main()
       {
           struct s {
               int i;
               char c;
               double d;
               char a[];
           };

           /* Output is compiler dependent */

           printf("offsets: i=%ld; c=%ld; d=%ld a=%ld\n",
                   (long) offsetof(struct s, i),    // s.i ?
                   (long) offsetof(struct s, c),    // s.c ?
                   (long) offsetof(struct s, d),    // s.d ?
                   (long) offsetof(struct s, a));    // s.a ?
           printf("sizeof(struct s)=%ld\n", (long) sizeof(struct s));

           exit(EXIT_SUCCESS);
       }


생각을 해보니..

$ vi /usr/inclue/net/if.h
152 # define ifr_name       ifr_ifrn.ifrn_name      /* interface name       */
153 # define ifr_hwaddr     ifr_ifru.ifru_hwaddr    /* MAC address          */
154 # define ifr_addr       ifr_ifru.ifru_addr      /* address              */
155 # define ifr_dstaddr    ifr_ifru.ifru_dstaddr   /* other end of p-p lnk */
156 # define ifr_broadaddr  ifr_ifru.ifru_broadaddr /* broadcast address    */
157 # define ifr_netmask    ifr_ifru.ifru_netmask   /* interface net mask   */
158 # define ifr_flags      ifr_ifru.ifru_flags     /* flags                */
159 # define ifr_metric     ifr_ifru.ifru_ivalue    /* metric               */
160 # define ifr_mtu        ifr_ifru.ifru_mtu       /* mtu                  */
161 # define ifr_map        ifr_ifru.ifru_map       /* device map           */
162 # define ifr_slave      ifr_ifru.ifru_slave     /* slave device         */
163 # define ifr_data       ifr_ifru.ifru_data      /* for use by interface */
164 # define ifr_ifindex    ifr_ifru.ifru_ivalue    /* interface index      */
165 # define ifr_bandwidth  ifr_ifru.ifru_ivalue    /* link bandwidth       */
166 # define ifr_qlen       ifr_ifru.ifru_ivalue    /* queue length         */
167 # define ifr_newname    ifr_ifru.ifru_newname   /* New name             */

이런식으로도 매크로 정의가 되어 있는데, 여러가지 방법으로 사용하는 이유가 있을까 라는 생각도 든다.

'Linux API > network' 카테고리의 다른 글

gateway 정보  (0) 2009.06.05
linux에서 ip/mac address 받아오기 관련 링크  (0) 2009.06.05
network 관련 include 할 파일 목록  (0) 2009.06.05
SIOCGIF가 모야?  (0) 2009.06.05
C언어로 MAC 어드레스 받아오기 (Linux)  (1) 2009.06.04
Posted by 구차니