[C] 네트워크 인터페이스에 관한 정보 - ioctl()
네트워크 인터페이스에 관한 정보를 알고 싶다면 ioctl() 시스템콜을 사용할 수 있습니다.
전형적인 운영체제는 2계층으로 나뉩니다. User Space(사용자 모드)와 Kenel Space(커널 모드).
User Space에 상주하는 애플리케이션이 Kenel Space에 존재하는 자원을 사용하고자할 땐 시스템콜을 이용합니다.
참고로, System Call Function은 내부적으로 System Call Vector와 대응됩니다. 예를들면, exit()함수는 System Call Vector Number: 1번
write()함수는 System Call Vector Number: 4번.
전형적인 운영체제의 커널은 수 백개의 System Call Vector를 제공합니다.
ioctl() 시스템콜은 디바이스 드라이버(Device Driver)와 통신하기위한 함수입니다.
디바이스 드라이버(Device Driver)?
아래 2가지 사실을 생각해봅시다.
1. 하드웨어 주변 장치는 커널 안에 직접적으로 주소지정을 할 수 있다.
2. 응용 프로그램이 장치와 통신하길 원할 수 있다.( 하드웨어 장치의 기능을 사용하고 싶을 때 )
그런데 커널 개발자는 어떤 장치가 커널 안에 주소를 할당받을지, 그 장치에는 어떤 기능이 있는지 알 지 못합니다.( 미리 예측할 수 없는 문제 )
이러한 문제점 때문에 확장가능한 모듈식으로 커널을 유연하게 설계할 필요가 있었고, 그렇게해서 나온게 디바이스 드라이버입니다.
즉, 어떠한 장치가 연결될지 모르는 상황에서 디바이스 드라이버라는 하나의 중간 계층(?)을 둠으로써 문제를 해결할 수 있었습니다.
ioctl() 함수는 struct ifreq 구조체를 매개변수로 받아 정보를 해당 구조체에 저장합니다. 다음 예제는 자신의 MAC Address 정보를 가져옵니다.
#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>
int main(int argc, char* argv[]) {
struct ifreq ifr;
u_char* macAddress;
u_char* interface = argv[1]; // argv[1]은 네트워크 인터페이스라 가정합니다. 예를 들어, ens33, eth0 eth1 ...
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, interface, IFNAMSIZ - 1); // ioctl의 대상으로 삼고자하는 인터페이스 이름을 ifr_name 멤버에 저장
ioctl(sock, SIOCGIFCONF, &ifr); // ioctl에 필요한 정보를 struct ifreq 구조체 데이터로 넘깁니다.
macAddress = (u_char*)ifr.ifr_hwaddr.sa_data; // ifr_hwaddr 멤버에 하드웨어 주소에 대한 정보가 담겨있습니다.
close(sock);
return 0;
}
다음은 struct ifreq 구조체의 구조입니다.
struct ifreq
{
# define IFHWADDRLEN 6
# define IFNAMSIZ IF_NAMESIZE
union
{
char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */
} ifr_ifrn;
union
{
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short int ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
char ifru_newname[IFNAMSIZ];
__caddr_t ifru_data;
} ifr_ifru;
};
# define ifr_name ifr_ifrn.ifrn_name /* interface name */
# define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
# define ifr_addr ifr_ifru.ifru_addr /* address */
# define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
# define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
# define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
# define ifr_flags ifr_ifru.ifru_flags /* flags */
# define ifr_metric ifr_ifru.ifru_ivalue /* metric */
# define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
# define ifr_map ifr_ifru.ifru_map /* device map */
# define ifr_slave ifr_ifru.ifru_slave /* slave device */
# define ifr_data ifr_ifru.ifru_data /* for use by interface */
# define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
# define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
# define ifr_qlen ifr_ifru.ifru_ivalue /* queue length */
# define ifr_newname ifr_ifru.ifru_newname /* New name */
# define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0)
# define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0)
# define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0)
'Programming > C C++' 카테고리의 다른 글
[C++ 문법] 배열 연산자 오버로딩 (0) | 2019.05.15 |
---|---|
[C++ 문법] 'const' 위치에 따른 멤버함수의 의미 (2) | 2019.05.15 |
[C] Reserved Names (0) | 2019.01.31 |
[C] C 프로그램의 컴파일 과정 (0) | 2019.01.30 |
[C] 동적 메모리 할당 ( Dynamic Memory Allocation ) (3) | 2019.01.11 |
댓글
이 글 공유하기
다른 글
-
[C++ 문법] 배열 연산자 오버로딩
[C++ 문법] 배열 연산자 오버로딩
2019.05.15 -
[C++ 문법] 'const' 위치에 따른 멤버함수의 의미
[C++ 문법] 'const' 위치에 따른 멤버함수의 의미
2019.05.15 -
[C] Reserved Names
[C] Reserved Names
2019.01.31 -
[C] C 프로그램의 컴파일 과정
[C] C 프로그램의 컴파일 과정
2019.01.30