Linux - 시그널 Signal (Ctrl+c, Ctrl+z)

Posted by ironmask84
2018. 5. 13. 00:39 나는 프로그래머다!/Linux



리눅스에서 Ctrl + C 키 조합을 통해 프로세스 종료를 많이 해보셨을 겁니다.

저 또한 그냥 개발시에 테스트 진행하다가 빨리 강제종료 시키기 위해 사용을 해왔었습니다.

그러다가 Ctrl + C가 먹히지 않는 프로세스가 발생하고는...

Ctrl + Z 를 어디선가 써본적이 있어! 라는 생각이 스쳐지나가면서 써보니 

뭔가 다시 콘솔창에 프롬프트가 상태가 되어 명령어 입력이 가능해집니다.

뭔가 근데 찜찜하기 시작합니다. 

알고 보니 이건 foreground process를 background로 전환하면서 잠깐 중지 시키는 것이더군요 ㅋㅋ

Ctrl + C와 Ctrl + Z 는 리눅스나 윈도우 같은 OS가 기본적으로 지원해주는 시스템호출을 통한 인터럽트 입니다!!

리눅스에서는 이러한 개념을 Signal 이라고 하는 것 같아요.

https://en.wikipedia.org/wiki/Unix_signal


Ctrl-C (in older Unixes, DEL) sends an INT signal ("interrupt", SIGINT); by default, this causes the process to terminate.

Ctrl-Z sends a TSTP signal ("terminal stop", SIGTSTP); by default, this causes the process to suspend execution.

Ctrl-\ sends a QUIT signal (SIGQUIT); by default, this causes the process to terminate and dump core.

Ctrl-T (not supported on all UNIXes) sends an INFO signal (SIGINFO); by default, and if supported by the command, this causes the operating system to show information about the running command.

These default key combinations with modern operating systems can be changed with the stty command.


좀 더 자세하고 다양한 내용은 아래를 참조하면 좋을 것 같습니다.

시그널의 명령어 리스트 : kill -l

시그널의 의미 (/usr/include/asm/signal.h)


자, 그럼 왜 Ctrl + C가 먹히지 않았을까..

검색을 해보자!!

리눅스 C 프로그래밍에는 signal() 이란 함수가 있습니다!!

프로세스에서 아래와 같이 호출하면, Ctrl + C가 무시되도록 설정됩니다!!

signal(SIGINT, SIG_IGN); // SIGINT 명령을 무시하도록 설정 


아래와 같이 handler를 추가해서 커스터마이즈한 활용도 가능합니다!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int  main(void)
{
     signal(SIGINT, INThandler);
     while (1)
          pause();
     return 0;
}
 
void  INThandler(int sig)
{
     char  c;
 
     signal(sig, SIG_IGN);
     printf("singnal test");
}

cs




 

Linux - 디렉토리 용량 확인

Posted by ironmask84
2018. 5. 13. 00:02 나는 프로그래머다!/Linux




회사에서 프로젝트 개발에 OS를 리눅스 Yocto를 사용하고 있는데,

아직 리눅스 사용이 아직 익숙하지가 않습니다.. 

임베디드 + CUI 환경이어서, 더욱 직관적이지가 않다보니...

윈도우에 익숙해온 것이 무서운 것인지.. 확실히 리눅스가 UI, UX 측면에서는 부족한 느낌입니다.

확실히 개발자에게 적합한 환경이랄까요.. CUI 환경자체가.. 단순하니 그런 것 같습니다.


아무튼 임베디드 환경은 용량이 제한적일 수 밖에 없습니다.

한번 쯤 디스크 용량 체크를 해보고 싶을 때가 오는데요.

적당한 명령어는 아래와 같습니다. ^^


du -h /폴더명 : 디렉토리별, 하위 디렉토리까지 확인

du -hs /폴더명 : 하위 디렉토리까지 확인

du -h --max-depth=2 디렉토리 : 디렉토리별 용량 확인

du -s 폴더명 : 해당 폴더의 용량

du -s ./* : 해당 폴더 소속 모든 폴더 용량.

df -h : 파티션 용량 확인




 

쓰레드 함수 (pthread) 알아 보기

Posted by ironmask84
2017. 8. 1. 09:46 나는 프로그래머다!/Linux



저는 쓰레드 프로그래밍을 JAVA언어로 먼저 배웠고, 사용해봤습니다.

흔히, 아래와 같은 예로 개념 이해를 시작하게 됩니다.
은행에 돈 인출을 한 계좌에서 2건이 거의 동시에 일어났을 때 순차적으로 거래가 이뤄지지 않고,
선 거래 건이 이뤄지기 전에 후 거래가 전산적으로 먼저 처리되는 꼬임 ㅋㅋ

아무튼 JAVA로 채팅 프로그램을 만들때 사용해보고,
실기시험을 통한 간단한 예시 정도로만 코딩을 해보고는
실무에서 직접 생성해서 적용하는 걸 거의 못해봤네요 ㅠㅠ
(거의 구현된 것을 디버깅 하는 경우가 많다보니..)

아무튼 그리하여, 이번 기회에 좀 더 이해하고 정리하는 기분으로 글 하나 작성합니다.

리눅스 환경이면 gcc가 있을테니 바로 사용가능하고,
윈도우의 경우 MinGW나 Cygwin을 설치하면 크로스 컴파일이 가능해집니다.

크로스 컴파일 --> http://ironmask.net/298


출처:

http://enst.tistory.com/95 [개발 이야기]



또한 1부터 num까지 세는 Thread는 하나씩 셀 때마다 1000마이크로 초(1ms)를 쉰다
쉬지 않으면 SumThread가 끝나기 전에 CountThread가 끝나버려서 Thread가 제대로 돌아갔는지 알 수 없기 때문이다.

PThread를 사용하려면 pthread.h를 인클루드 시켜줘야 한다.
또한 pthread_t 라는 자료형의 변수와 함수들을 사용해 thread를 제어한다.

pthread_t라는 변수형은 thread의 id를 저장한다.

이 프로그램에서 사용한 함수들은 이렇다.

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);

이 함수는 thread를 생성하는 함수이다.
첫번째 인자는 생성할 thread의 id
두번째 인자는 thread의 특성인데, 보통 NULL을 집어넣는다.
세번째 인자는 thread를 실행할 함수가 온다. thread를 실행할 함수는 포인터 함수이므로 인자값으로 올 수 있다.
네번째 인자는 thread를 실행할 함수에 넣어줄 인자값이 온다. 인자값은 하나지만 여러개의 인자값을 넣어주는 꼼수도 존재한다.(이건 다음에 포스팅)

int pthread_join(pthread_t thread, void **rval_ptr);

이 함수는 main이나 부모 thread에서 자식 thread가 종료할 때까지 대기하는 함수이다. main이나 부모thread가 끝나버리면 자식 thread 또한 종료되기 때문이다.
첫번째 인자는 생성한 thread의 id
두번째 인자는 해당 thread가 종료되면 return받을 변수. 리턴받을 값이 없으면 NULL을 넣으면 된다.

void pthread_exit(void *rval_ptr);


이 함수는 thread를 종료할 때 사용한다.
첫번째 인자는 thread를 종료하고 pthread_join() 함수 두번째 인자에 리턴할 변수. 리턴할 값이 없으면 NULL을 넣으면 된다.

pthread_t pthread_self(void)

이 함수는 실행하고 있는 thread의 id를 리턴한다.


또한 gcc에서 PThread를 사용할 소스를 컴파일 할때 맨 뒤에 -lpthread 명령어를 붙여줘야 한다.





이런식으로
MinGW로 컴파일 할때도 마찬가지.

아래는 소스.

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
#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
 
void *CountThread(void *); 
void *SumThread(void *); 
 
int main(void
int num; 
int result[2]; 
int i, rc; 
pthread_t threads[2]; 
 
printf("input number : "); 
scanf("%d"&num); 
 
pthread_create(&threads[0], NULL&CountThread, (void *)&num); //Count를 할 Thread함수를 threads[0]에서 실행(인자값은 num) 
pthread_create(&threads[1], NULL&SumThread, (void *)&num); //Sum을 구할 Thread함수를 threads[1]에서 실행(인자값은 num) 
 
for(i = 0; i < 2; i++
rc = pthread_join(threads[i], (void **)&result[i]); 
 
if(rc != 0//rc가 0이 아니면 오류 발생 
printf("Error in thread[%d] : %d\n", i, rc); 
exit(1); 
 
printf("Result of CountThread : %d\n", result[0]); 
printf("Result of SumThread : %d\n", result[1]); 
 
return 0
 
void *CountThread(void *arg) 
int i; 
int num = *(int *)arg; //인자값을 사용해야할 때마다 일일이 void* 포인터에서 int* 포인터로 바꿔줘야 해서 귀찮아지므로 그냥 변수를 하나 만들어서 인자값을 넣어줌 
 
for(i = 1; i <= num; i++
printf("In CountThread(0x%lx) : %d\n", pthread_self(), i); 
usleep(1000); 
 
printf("CountThread End\n"); 
pthread_exit(NULL); //인자값을 return하고 Thread함수 종료 
 
void *SumThread(void *arg) 
int result, i; 
int num = *(int *)arg; 
 
for(result = 0, i = 1; i <= num; i++
result += i; 
 
printf("SumThread End\n"); 
pthread_exit((void *)result); //인자값을 return하고 Thread함수 종료(인자값이 void형 포인터로 들어가므로 void형 포인터로 형변환) 
 
 

cs


좀 더 간단한 예시

- 아규먼트를 사용하지 않는 함수의 경우

- arg에 NULL 을 삽입하여 생성

- 아규먼트를 받는 함수의 경우

-arg를 통해 아규먼트를 함께 넘겨주어야 함

void *

- pthread_create 함수 타입

- 아규먼트/반환 타입이 void * 인 함수를 실행

- void * 인 이유

- void * 는 주로 임의의 data type을 가리키는 용도로 사용

- 임의의 data type을 아규먼트/반환 값으로 넘겨줄 수 있음

단일 아규먼트 전달

- 아규먼트로 정수 n을 받고 0 ~ n-1 의 숫자를 출력하는 경우

- pthread_create의 마지막 아규먼트 사용(void * 로 integer 변수를 가리킴)

- main 스레드의 경우

- 아규먼트(n)를 가리키는 포인터 설정

- 포인터를 아규먼트로 넘김  

ex) Main 함수의 n 값을 아규먼트로 받아 Thread에서 0 ~ n 까지의 값을 출력

출처: http://ypangtrouble.tistory.com/70 [끄적끄적 소소한 일상]



참고:

http://underresearch.blogspot.kr/2013/05/pthread-thread.html

http://www.joinc.co.kr/w/Site/Thread/Beginning/PthreadApiReference#AEN226

http://www.morenice.kr/75

http://www.joinc.co.kr/w/Site/system_programing/Book_LSP/ch07_Thread

http://m.blog.naver.com/cky5122/80198083088

http://www.joinc.co.kr/w/Site/Thread/Beginning/PthreadApiReference#AEN226

https://kldp.org/node/93835

http://blog.naver.com/rbosc/90016327317





 

Linux 명령어와 시스템보안

Posted by ironmask84
2017. 3. 3. 18:23 컴퓨터공학/Security


1. ls (디렉터리, 파일 정보 출력)
-> 1) 파일종류, 접근권한  2) 하드링크수  3) 소유주  4) 소유그룹  5) 크기  6) 최종 변경일  7) 최종 변경시간  8) 이름

2. stat (i-node 속성정보 출력)
-> 1) i-node number  2) 파일타입  3) 접근권한  4) link count  5) 소유자  6) 소유그룹  7) 크기  8) MAC Time  
    9) Block Index
    ln source_file target_file : 하드링크 
    ln -s source_file target_file : 심볼릭링크 (소프트 링크)

3. find (파일 검색)
-> find path [expression] [action]
    1) find . -name "*.c" : 현재 디렉터리에서 파일명이 .c로 끝나는 파일 검색
    2) find . -size +56 : 현재 디렉터리에서 파일 크기가 56블록보다 큰 것을 검색
    3) find . -perm -664 : 현재 디렉터리에서 user와 group에 읽기 및 쓰기 권한, other에 읽기 권한이 있는 파일 검색
    4) find . -mtime +3 : 현재 디렉터리에서 파일을 수정한지 3일이 지난 것을 검색

4. touch : 0byte 파일을 생성 또는 파일의 시간을 변경

5. umask : 파일 생성 시 접근권한에 영향을 미침 (/etc/profile 에 적용, 개인은 .profile에 적용)

6. diff : 파일이 동일한지 여부를 검사

7. comm : 파일을 비교할 때 사용 (한쪽에만 있거나 양쪽 모두에 있는 행 출력)

8. grep : 파일 내 특정 패턴이나 문자열을 검색

9. ps : 시스템에 상주중인 프로세스 정보 출력
-> UID, PID, PPID, STIME(프로세스 시작 시간), TTY(프로세스가 연결된 터미널), TIME(CPU 사용시간), CMD(프로세스명)

10. 시그널 : UNIX 시스템에서 지원하는 소프트웨어 인터럽트, 프로세스간 통신수단
-> 1) 외부에 의해서 : 키보드 입력 (ctrl + c)
    2) (커널)에러에 의해서 : divde zero 오류, 메모리 참조 오류
    3) 이벤트에 의해서 : alarm() 함수, 프로세스 종료
    4) 인위적으로 : kill() 함수, kill 명령어 (kill -시그널번호 PID)
  * 주요시그널 : SIGKILL(9), SIGSTOP(23) 이 2가지는 무시나 핸들링이 불가능하므로 관리자가 해커를 막기위한 강력권한
  * 좀비프로세스 : 프로세스 수행을 종료했지만 부모 프로세스가 종료상태정보를 확인하지 않아서 소멸하지 않고
                        남아있는 프로세스
  * 고아프로세스 : 자식프로세스가 살아있는 상태에서 부모 프로세스가 종료하게 되면 자식프로세스는 고아프로세스 됨.

11. mount : 보조기억장치에 설치된 파일시스템을 UNIX시스템이 인식하도록 특정 디렉토리에 논리적으로 연결시킴

12. cron : 정기적 처리할 작업을 crontab명령으로 crontab파일에 저장, cron데몬 프로세스가 관리
              해커가 주기적으로 정보를 빼돌리는 데에 사용도 가능하다. -> crobtab 파일 관리 필요

13. /etc/passwd : account / password(x로표시) / user_ID / group_ID / comment / home_directory / login_shell
    /etc/shadow : account / encrypted_password / last_change / minlife / maxlife / warn / inactive / expires
      ** chage 명령어로 패스워드 Aging관련 설정을 할 수 있다. -> /var/log/secure파일에 로그가 남는다.

14. setuid, setgid (chmod ug+s)
   1) setuid, setgid 설정된 경우 -> RUID == EUID,  RGID == EGID
   2) setuid, setgid 설정되지 않은 경우
   -> RUID, RGID = 실행시킨 사용자의 ID
       EUID, EGID  = 실행파일 소유자의 ID (프로세스가 실행중인 동안에 접근권한을 판단하기 위한 ID)
* root소유의 실행파일에 setuid를 설정하면, ruid는 실행자의 id, euid는 root id로 설정이 된다. 
  따라서, 실행 프로그램 내에 euid 설정에 따라 root권한으로 접근하게 된다.

* sticky bit (chmod o+t)
-> 디렉토리에 설정이 되면, 파일의 생성은 자유롭게 할 수 있지만
    파일 삭제 및 파일명 변경은 파일소유자 또는 root만이 가능하다.



 

Container_of 매크로

Posted by ironmask84
2016. 11. 9. 11:01 나는 프로그래머다!/Linux


Linux 소스 스터디 입문을 했습니다.

"리눅스 커널과 디바이스드라이버 실습2" 라는 책을 구입 후 보는 중인데,
리눅스에서 주로 사용하는 자료구조 쪽을 공부하다보니,
(기준 리눅스 커널 버젼은 2.6.31 이라고 합니다.)

소스 내에 container_of(ptr, type, member) 이라는 매크로를 소개하네요..
이름만 봐서는 argument들의 container.. 즉, C언어이니 구조체를 리턴해줄 것으로 보이는데,
container의 주소값을 얻는데 사용하는 것 같습니다.

첫 느낌은 뭔가 디게 복잡하게 주소값을 얻어오는 기분입니다만.. 이게 최선인가;;
매크로는 아래와 같습니다.

#define offsetof(TYPE, MEMBER) ((unsigned long) & ((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({ \

const typeof( ((type *)0)->member ) *_mptr = (ptr); \

(type *)( (char *)_mptr - offsetof(type, member) ); })

실제로 console로 결과값을 돌려보고, 머리를 굴려봐도 머리에 잘 안들어오네요 ㅜㅜ

검색하다가 리뷰가 잘되어있는 주소 링크합니다.
http://rootfriend.tistory.com/197
http://kldp.org/node/58409

주요내용은 아래에 따로 펌~

gcc C 언어 확장 기능으로, (즉, 표준이 아니며, 다른 컴파일러에서 지원하지 않는..) compound statement (중괄호로 둘러싼 여러 statement)를 expression으로 해석하는 기능이 있습니다. 예를 들면:

({ int y = foo(); int z;
if (y > 0) z = y;
else z = - y;
z; })


로 쓴 것처럼, foo() 리턴 값의 절대값을 얻는 코드를 위와 같이 작성할 수 있습니다. 이 것은 C99 표준에서 inline function이 나오기 전에 매우 유용하게 썼던 기능입니다. expression에서 switch, for 등의 statement를 쓸 수 있는 등의 장점을 얻을 수 있었습니다. 실제로 GNU C library에 포함되어 있는 obstack에 관계된 대부분의 함수가 이 compound-statement expression을 써서 macro로 구현되어 있습니다. 물론 맨 마지막 statement의 값이, 이 compound statement의 값이 됩니다.

그런데, 이 기능은 현재 C++에서 쓸 경우, 임시 변수의 destructor가 불리는 순서가 바뀌는 등의 단점이 있기 때문에, C++로 쓸 우려가 있는 코드에서는 이 compound statement expression을 쓰지 말라고 권하고 있습니다.

개인적으로 간단한 수식으로 나올 수 있는 것이 아니라면 do { ... } while (0)을 써서 macro로 만들고, 어떤 값을 리턴할 필요가 있는 macro라면 inline function을 쓰는 것이 좋다고 생각합니다.