rtl8723ae driver in Gentoo

노트북에 젠투 설치 후, 부팅을 하면 이상하게 무선랜이 안잡히는 현상이 발생했다.
처음 설치할 당시, USB로 부팅 했을 때에는 잘 잡히던 무선랜이 USB 제거 후, 노멀부팅을 하면 안잡히는 것이다.

혹시나 커널 컴파일 할 때, 깜박하고 해당 모듈을 설치 안한건 아닐까 싶어서 확인을 해 봤으나 이미 설치가 되어있는 상태였다.

pchero@localhost /usr/src/linux $ grep 8723 .config
CONFIG_RTL8723AE=y

먼저 dmesg 로 어디가 문제인지를 살펴보았다.

다음의 부분이 확인되었다.

[    0.316869] pci 0000:02:00.0: [10ec:8723] type 00 class 0x028000
[   13.595185] usb 2-1.3: New USB device found, idVendor=0bda, idProduct=8723
[   17.805554] rtl8723ae: Using firmware rtlwifi/rtl8723fw_B.bin
[   17.805585] rtl8723ae 0000:02:00.0: Direct firmware load failed with error -2
[   17.805588] rtl8723ae 0000:02:00.0: Falling back to user helper
[   17.806024] rtlwifi: Firmware rtlwifi/rtl8723fw_B.bin not available

마지막 라인. rtlwifi: Firmware rtlwifi/rtl8723fw_B.bin not available 즉, rtlwifi/rtl8723fw_B.bin파일이 없다는 것이다.

왜 없을까… 이유는 둘째치고 일단 해당 파일을 구해보기로 했다.

git 명령으로 구할 수 있다.

git clone git://git.kernel.org/pub/scm/linux/kernel/git/dwmw2/linux-firmware.git /lib64/firmware/

이후 재부팅시 해당 모듈이 정상적으로 올라오는 것을 확인할 수 있다.
하지만 dmesg 내용을 확인해 보면 역시나 같은 오류 메시지를 확인할 수 있다.

localhost ~ # dmesg |grep 8723
[    0.316576] pci 0000:02:00.0: [10ec:8723] type 00 class 0x028000
[    2.257211] rtl8723ae: Using firmware rtlwifi/rtl8723fw_B.bin
[    2.258245] rtl8723ae 0000:02:00.0: Direct firmware load failed with error -2
[    2.259305] rtl8723ae 0000:02:00.0: Falling back to user helper

어찌된 일일까? 아마도 Direct firmware 로그는 실패했지만, rtlwifi 모듈이 정상적으로 올라와서 그런거 같다.

[   17.475458] rtlwifi: wireless switch is on

debuginfo-install

man debuginfo-install

debuginfo-install(1)                                      debuginfo-install(1)

NAME
debuginfo-install

SYNOPSIS
debuginfo-install package

DESCRIPTION
debuginfo-install  is  a  program  which  installs the RPMs needed to debug the specified package.  The package argument can be a wildcard, but will only match installed pacakges.  debuginfo-install will then
enable any debuginfo repositories, and install the relevant debuginfo rpm.

EXAMPLES
Download and install all the RPMs needed to debug the kernel RPM:
debuginfo-install kernel

WARNING MESSAGES
Could not find debuginfo for:
if you run debuginfo-install for a wildcard or glob. Debuginfo packages are not necessary for “noarch” RPMs; these will generate a warning message.  Additionally, On 64-bit systems, no multilib  debug-
info packages are published, so if you have 32-bit packages installed, these will also generate warning messages.

FILES
As debuginfo-install uses YUM libraries for retrieving all the information, it relies on YUM configuration for its default values like which repositories to use. Consult YUM documentation for details:

/etc/yum.conf
/etc/yum/repos.d/
/var/cache/yum/

SEE ALSO
yum.conf (5)
http://yum-utils.baseurl.org/
http://yum.baseurl.org/

AUTHORS
See the Authors file included with this program.

BUGS
There  are  of  course  no bugs, but should you find any, you should first consult the FAQ section on http://yum.baseurl.org/wiki/Faq and if unsuccessful in finding a resolution contact the mailing list: yum-
devel@lists.baseurl.org.  To file a bug use http://bugzilla.redhat.com for Fedora/RHEL/Centos related bugs and http://yum.baseurl.org/report for all other bugs.

James Antill                    21 October 2008           debuginfo-install(1)

debuginfo-install 명령어는 rpm/yum 으로 설치한 바이너리 패키지들이 crash dump 가 발생했을 때, gdb를 이용하여 디버깅을 할 때 필요한 패키지들을 설치하는 명령어이다.
물론, rpm/yum 으로도 해당 패키지들의 설치가 가능하다. 단, 정확한 패키지명을 입력해야만 한다.

마찬가지로, ubuntu 에서도 apt-get 으로 설치한 패키지들의 디버깅을 위한 debuginfo 패키지를 제공한다.
그러나, debuginfo-install 명령으로 설치하는 것이 아닌 apt-get 명령어로 설치해야 한다. 설치해야되는 debug 패키지들의 패키지 명은 패키지명-dbg 로 입력하면 된다.

현재 회사에서는 개발된 제품들을 배포할때 rpm으로 제작하여 배포를 한다.
이렇게, rpm 으로 제작된 패키지들에 대하여 코어 파일이 발생하고, 디버깅을 해야 할 때, 앞서 언급한 debuginfo 패키지를 설치한 뒤, 디버깅을 한다.

이렇게 작업을 하게 되면, 디버깅을 할 때, 별도의 소스코드 없이도 rpm 패키지들로만으로도 코어 분석이 가능하게 된다.

setting of remote system environment for eclipse

원격지에서 ssh 통신으로 접속해서 작업을 하는데 eclipse 연동으로 작업을 하고 싶다면???

ssh key 복사 + sshfs + eclipse  구성이 정답이다.

ssh key 복사를 통해, ssh 접속시 비밀번호를 입력하지 않고도 바로 접속이 되도록 설정하고, sshfs 로 원격지 파일 시스템을 로컬 파일 시스템에 마운트한다.
그 다음, eclipse 를 통해 작업을 하는 것이다.

먼저 비밀번호 없이 ssh 로 접속하는 설정이 필요하다.다음을 참고하자.

http://pchero21.com/3034

이제 sshfs 를 구성하자. 아직 sshfs 가 설치되어 있지 않다면 다음의 명령어를 입력하자.

$ sudo apt-get install sshfs

이제 작업 공간 디렉토리를 마운트 시키자.

sshfs stk@test_server:absoulte_work_directory_path_of remote absoulte_mount_position_of_local

이제 eclipse 로 프로젝트를 하나 생성해서 프로젝트 위치를 방금 마운트 한 곳으로 지정하자.

그리고, 생성한 프로젝트에서 C/C++ Build -> Builder Settings -> Build command 항목을 아래와 같이 수정해주자.

ssh pchero@10.0.6.12 ‘bmake -C Absolute_path_for_working_directory_of_remote’

이제 프로젝트를 빌드할 때, 원격지에서 빌드를 수행하는 것을 확인할 수 있다.(필자는 bmake 를 사용하므로 bmake를 입력했다. 만약 gnu-make 를 사용한다면 그냥 make를 입력하도록 하자.)

한가지 단점이라면, 구성 자체가 ssh로 먼저 접속을 한 다음, 뒤따라오는 명령어를 수행하는 방식이기 때문에…
매번 빌드를 할 때마다 ssh 접속 오버헤드가 발생한다는 점이다.

ssh 는 RSA 키 조합의 특성으로 접속시 다소 시간이 오래 걸리는 편이다. 때문에 필자의 경우, sshfs를 통한 파일시스템 마운트 후, 빌드는 ssh 를 통하지 않고, 로컬 머신에서 하는 것으로 구성했다.

출처: http://sunjinyang.wordpress.com/2008/08/11/eclipse-with-remote-ssh-server/

Libevent event driven memory leak

진행중인 프로젝트에서 Libevent 를 사용중인데.. valgrind 메모리 누수 확인시 자꾸 메모리 누수가 발생하는 것을 확인했다.

어디가 문제일까… 기능상으로는 문제가 없었다.
malloc/calloc 할당한 부분도 문제가 없었다.
valgrind 가 지목한 문제 발생한 부분은 event_new() 부분이었다.

문제 발생 원인은 잘못된 libevent 사용에 있었다.
나는 다음과 같이 프로그램을 개발했었다.

/*
* main.c
*
* Copyright 2014 Sungtae Kim <pchero21@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <event2/event.h>

typedef struct _wctx
{
struct event_base*  w_base;     // main base
} wctx;

static void cb_main_listen(__attribute__ ((__unused__)) int fd, __attribute__ ((__unused__)) short event, void *arg);
static void cb_process(__attribute__ ((__unused__)) int fd, __attribute__ ((__unused__)) short event, void *arg);
static void cb_process_detail(__attribute__ ((__unused__)) int fd, __attribute__ ((__unused__)) short event, void *arg);

int main(int argc, char **argv)
{

wctx* work = calloc(1, sizeof(wctx));

work->w_base = event_base_new();
struct event* main_listen = event_new(work->w_base, STDIN_FILENO, EV_READ, cb_main_listen, work);
event_add(main_listen, NULL);

event_base_dispatch(work->w_base);

printf(“System terminate…n”);
event_free(main_listen);
event_base_free(work->w_base);

return 0;
}

static void cb_main_listen(__attribute__ ((__unused__)) int fd, __attribute__ ((__unused__)) short event, void *arg)
{
wctx* work = (wctx*)arg;
struct event* w_event = evtimer_new(work->w_base, cb_process, work);

struct timeval  tVal;
tVal.tv_sec = 0;
tVal.tv_usec = 0;
evtimer_add(w_event, &tVal);
}

static void cb_process(__attribute__ ((__unused__)) int fd, __attribute__ ((__unused__)) short event, void *arg)
{
printf(“Process!!n”);
wctx* work = (wctx*)arg;
struct event* w_event = evtimer_new(work->w_base, cb_process_detail, work);

struct timeval  tVal;
tVal.tv_sec = 0;
tVal.tv_usec = 0;
evtimer_add(w_event, &tVal);

}

static void cb_process_detail(__attribute__ ((__unused__)) int fd, __attribute__ ((__unused__)) short event, void *arg)
{
printf(“Detail Process!!n”);
}

 

아래는 valgrind 로 메모리 누수를 확인한 내용이다.

pchero@MyGalaxy:~/workspace/Study/Program/LibEvent/memory_leak$ echo “Hello” | valgrind –leak-check=full ./main
==2222== Memcheck, a memory error detector
==2222== Copyright (C) 2002-2012, and GNU GPL’d, by Julian Seward et al.
==2222== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==2222== Command: ./main
==2222==
Process!!
Detail Process!!
System terminate…
==2222==
==2222== HEAP SUMMARY:
==2222==     in use at exit: 280 bytes in 3 blocks
==2222==   total heap usage: 12 allocs, 9 frees, 1,848 bytes allocated
==2222==
==2222== 136 bytes in 1 blocks are definitely lost in loss record 2 of 3
==2222==    at 0x4C2A2DB: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2222==    by 0x4E43A46: event_new (in /usr/lib/x86_64-linux-gnu/libevent-2.0.so.5.1.9)
==2222==    by 0x400A16: cb_process (main.c:73)
==2222==    by 0x4E41F93: event_base_loop (in /usr/lib/x86_64-linux-gnu/libevent-2.0.so.5.1.9)
==2222==    by 0x400933: main (main.c:49)
==2222==
==2222== 144 (136 direct, 8 indirect) bytes in 1 blocks are definitely lost in loss record 3 of 3
==2222==    at 0x4C2A2DB: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2222==    by 0x4E43A46: event_new (in /usr/lib/x86_64-linux-gnu/libevent-2.0.so.5.1.9)
==2222==    by 0x4009A1: cb_main_listen (main.c:61)
==2222==    by 0x4E41F93: event_base_loop (in /usr/lib/x86_64-linux-gnu/libevent-2.0.so.5.1.9)
==2222==    by 0x400933: main (main.c:49)
==2222==
==2222== LEAK SUMMARY:
==2222==    definitely lost: 272 bytes in 2 blocks
==2222==    indirectly lost: 8 bytes in 1 blocks
==2222==      possibly lost: 0 bytes in 0 blocks
==2222==    still reachable: 0 bytes in 0 blocks
==2222==         suppressed: 0 bytes in 0 blocks
==2222==
==2222== For counts of detected and suppressed errors, rerun with: -v
==2222== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)

메모리 누수가 확인되는 지점이 두 곳이 보인다. 모두 event_new 를 했던 곳이다. 내용인즉, event_new() 를 통해 생성한 event를 따로 정상 삭제하지 않았다는 내용이다.
나는 timer 에 등록할 경우, 시간이 되어 함수가 작동할 경우, libevent 에서 자동으로 메모리를 해제해 주는 줄 알았다.
하지만 아니었다…

결국, 소스를 다음과 같이 수정하였다.

/*
* main.c
*
* Copyright 2014 Sungtae Kim <pchero21@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <event2/event.h>

typedef struct _wctx
{
struct event_base*  w_base;     // main base
struct event*       w_event;    // work event
} wctx;

static void cb_main_listen(__attribute__ ((__unused__)) int fd, __attribute__ ((__unused__)) short event, void *arg);
static void cb_process(__attribute__ ((__unused__)) int fd, __attribute__ ((__unused__)) short event, void *arg);
static void cb_process_detail(__attribute__ ((__unused__)) int fd, __attribute__ ((__unused__)) short event, void *arg);

int main(int argc, char **argv)
{

wctx* work = calloc(1, sizeof(wctx));

work->w_base = event_base_new();
struct event* main_listen = event_new(work->w_base, STDIN_FILENO, EV_READ, cb_main_listen, work);
event_add(main_listen, NULL);

event_base_dispatch(work->w_base);

printf(“System terminate…n”);
event_free(main_listen);
event_base_free(work->w_base);
free(work);

return 0;
}

static void cb_main_listen(__attribute__ ((__unused__)) int fd, __attribute__ ((__unused__)) short event, void *arg)
{
wctx* work = (wctx*)arg;
//    struct event* w_event = evtimer_new(work->w_base, cb_process, work);
work->w_event = evtimer_new(work->w_base, cb_process, work);

struct timeval  tVal;
tVal.tv_sec = 0;
tVal.tv_usec = 0;
//    evtimer_add(w_event, &tVal);
evtimer_add(work->w_event, &tVal);
}

static void cb_process(__attribute__ ((__unused__)) int fd, __attribute__ ((__unused__)) short event, void *arg)
{
printf(“Process!!n”);
wctx* work = (wctx*)arg;
//    struct event* w_event = evtimer_new(work->w_base, cb_process_detail, work);
evtimer_assign(work->w_event, work->w_base, cb_process_detail, work);

struct timeval  tVal;
tVal.tv_sec = 0;
tVal.tv_usec = 0;
//    evtimer_add(w_event, &tVal);
evtimer_add(work->w_event, &tVal);
}

static void cb_process_detail(__attribute__ ((__unused__)) int fd, __attribute__ ((__unused__)) short event, void *arg)
{
printf(“Detail Process!!n”);
wctx* work = (wctx*)arg;
event_free(work->w_event);
}

소스 수정 후, 다시 valgrind 를 돌려보았다.

pchero@MyGalaxy:~/workspace/Study/Program/LibEvent/memory_leak$ echo “Hello” | valgrind –leak-check=full ./main
==2440== Memcheck, a memory error detector
==2440== Copyright (C) 2002-2012, and GNU GPL’d, by Julian Seward et al.
==2440== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==2440== Command: ./main
==2440==
Process!!
Detail Process!!
System terminate…
==2440==
==2440== HEAP SUMMARY:
==2440==     in use at exit: 0 bytes in 0 blocks
==2440==   total heap usage: 11 allocs, 11 frees, 1,720 bytes allocated
==2440==
==2440== All heap blocks were freed — no leaks are possible
==2440==
==2440== For counts of detected and suppressed errors, rerun with: -v
==2440== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

결과는 성공!

문제 해결의 포인트는 다음과 같았다.

1. event_new()/evtimer_new() 의 사용을 줄이는 것. 가능하면 event_assign()/evtimer_assign() 을 사용하도록 했다.
2. new() 가 있으면 free() 도 해 준다는 것.

ssh private key copy

ssh 개인키 정보를 접속하는 서버에 복사를 하게 되면, ssh 접속시, 별도로 비밀번호 입력없이 접속이 가능해 편리하다.

아직 ssh 개인키를 생성하지 않았다면 새로 생성하자.

$ ssh-keygen

이후, ~/.ssh 디렉토리에 개인키와 공개키 파일이 생성되는 것을 확인할 수 있다.

pchero@MyGalaxy:~/.ssh$ ls
id_rsa  id_rsa.pub  known_hosts

id_rsa 파일이 개인키 파일이고, id_rsa.pub 파일이 공개키 파일이다. ssh 통신에서 개인키 파일은 전자 상거래에서의 공인 인증서이다. 잘 보관하자.

 

이제 생성된 공개키 내용을 접속하고자 하는 ssh 서버에 입력해줘야 한다.접속하고자 하는 ssh 서버 계정의 ~/.ssh/authorized_keys 파일에 넣어줘야 한다.

만약 파일이 없다면 새로 생성하면 된다. 공개키 파일의 내용은 모두 TEXT 이므로 잘 긁어서 넣어주자.

이후, 테스트로 ssh 접속을 해보자. 비밀번호 입력없이 접속이 된다면 성공이다.만약 모두 정상적으로 입력했는데도 실패한다면, 다음을 참고하자.

필자의 경우, 암호 없이 ssh 접속이 안되어 ssh 로그 파일을 살펴보니 다음의 내용을 확인할 수 있었다.

Feb 17 17:44:29 stk-centos-6-x64-development sshd[5855]: Authentication refused: bad ownership or modes for file /home/pchero/.ssh/authorized_keys
Feb 17 17:44:36 stk-centos-6-x64-development sshd[5855]: Accepted password for pchero from 10.1.27.69 port 59982 ssh2
Feb 17 17:44:36 stk-centos-6-x64-development sshd[5855]: pam_unix(sshd:session): session opened for user pchero by (uid=0)
Feb 17 17:45:42 stk-centos-6-x64-development sshd[5861]: Received disconnect from 10.1.27.69: 11: disconnected by user
Feb 17 17:45:42 stk-centos-6-x64-development sshd[5855]: pam_unix(sshd:session): session closed for user pchero
Feb 17 17:46:49 stk-centos-6-x64-development sshd[5891]: Authentication refused: bad ownership or modes for file /home/pchero/.ssh/authorized_keys
Feb 17 17:46:50 stk-centos-6-x64-development sshd[5892]: Connection closed by 10.1.27.69

내용인즉, authorized_keys 파일의 퍼미션이 올바르지 않다는 것. 해당 파일의 퍼미션을 600 으로 바꿔주니 접속이 잘 되었다.

만약 위의 방법이 복잡하다면 다른 방법도 있다.

가장 쉬운 방법은 ssh-copy-id 를 사용하는 것이다.

ssh-copy-id user@hostname.example.com

이 명령어 하나면 자신의 공개키가 복사되고, 이후, 비밀번호 없이 ssh 접속이 가능해진다.