|
Language/C 2012. 4. 10. 14:57
0000 0000 000 000 00 NUL NULL 문자 0000 0001 001 001 01 SOH 헤더 시작(Start Of Header) 0000 0010 002 002 02 STX 본문 시작, 헤더 종료(Start of TeXt) 0000 0011 003 003 03 ETX 본문 종료(End of TeXt) 0000 0100 004 004 04 EOT 전송 종료, 데이터 링크 초기화(End Of Transmission) 0000 0101 005 005 05 ENQ 응답 요구(ENQuiry) 0000 0110 006 006 06 ACK 긍정응답(ACKnowledge) 0000 0111 007 007 07 BEL 경고음(BELl) 0000 1000 008 010 08 BS 박스페이스(BackSpace) 0000 1001 009 011 09 HT 수평 탭(Horizontal Tab) 0000 1010 010 012 0A LF 개행(Line Feed) 0000 1011 011 013 0B VT 수직 탭(Vertical Tab) 0000 1100 012 014 0C FF 다음 페이지(Form Feed) 0000 1101 013 015 0D CR 복귀(Carriage Return) 0000 1110 014 016 0E SO 확장문자 시작(Shift Out) 0000 1111 015 017 0F SI 확장문자 종료(Shift In) 0001 0000 016 020 10 DLE 전송제어 확장(Data Link Escape) 0001 0001 017 021 11 DC1 장치 제어(Device Control 1) 0001 0010 018 022 12 DC2 장치 제어(Device Control 2) 0001 0011 019 023 13 DC3 장치 제어(Device Control 3) 0001 0100 020 024 14 DC4 장치 제어(Device Control 4) 0001 0101 021 025 15 NAK 부정응답(Negative AcKnowledge) 0001 0110 022 026 16 SYN 동기(SYNnchronous idle) 0001 0111 023 027 17 ETB 전송블록 종료(End of Transmission Block) 0001 1000 024 030 18 CAN 개무시(CANcel) 0001 1001 025 031 19 EM 매체 종료(End of Medium) 0001 1010 026 032 1A SUB 치환(SUBstitute) 0001 1011 027 033 1B ESC 제어기능 추가(ESCape) 0001 1100 028 034 1C FS 파일경계 할당(File Seperator) 0001 1101 029 035 1D GS 레코드 그룹경계 할당(Group Seperator) 0001 1110 030 036 1E RS 레코드경계 할당(Record Seperator) 0001 1111 031 037 1F US 장치경계 할당(Unit Seperator) 0010 0000 032 040 20 SPC 스페이스(SPaCe) |
Language/C 2012. 4. 6. 17:40
Frank Cusack wrote On 06/18/07 12:28,: > On Mon, 18 Jun 2007 15:51:08 -0000 Bin Chen wrote: > >>On Jun 18, 11:44 pm, Herman.Schu...@gmail.com wrote: >> >>>Hi, >>> >>>I am trying to print out the thread id in my program. >>> static pthread_t GetCurrentThreadID() { return :thread_self(); } >>> >>>void myFunction() { >>>pthread_t id = GetCurrentThreadID(); >>> >>> printf (" thread id %d\n", id); >>> >>>} >>> >>>But I get a negative number: -122112944. Did I do something wrong? >>>Why the number is negative? > > > Because %d is an integer type and prints both positive and negative > numbers. The thread id happens to be very large and is treated as a > negative integer. > > >>The pthread_t is defined as an unsigned variable, > > > No it isn't. It's an opaque type. > > printf("%lu\n", (unsigned long) id);
And even that won't always work: pthread_t is *really* opaque, and need not be a type to which a cast operator can be applied. On at least one implementation, pthread_t is a struct.
-- Eric.Sosman@sun.com
- http://fixunix.com/unix/84437-how-print-out-thread-id-pthread_t.html
Language/C 2012. 3. 16. 18:10
Anwendung von ANSI-Escape-Steuerfolgen
Beispiel 1:
Realisierung einiger Funktionen zur Arbeit mit Bildschirm und Cursor - Variante 1
#include <stdio.h>
#define ESC 27
void home(void)
{
printf("%c%s", ESC, "[1;1H");
}
void cursor(unsigned zeile, unsigned spalte)
{
printf("%c%c%02d%c%02d%c", ESC, '[', zeile, ';', spalte, 'H');
}
void store_cursor(void)
{
printf("%c%s", ESC, "[s");
}
void reset_cursor(void)
{
printf("%c%s", ESC, "[u");
}
void color(unsigned bg, unsigned fg)
{
printf("%c%c%02d%c%02d%c", ESC, '[', bg, ';', fg, 'm');
}
void colour(unsigned bg, unsigned fg, unsigned fmt)
{
printf("%c%c%02d%c%02d%c%1d%c", ESC, '[', bg, ';', fg, ';', fmt, 'm');
}
void normal()
{
printf("%c%s", ESC, "[0m");
}
void clear(void)
{
printf("%c%s", ESC, "[2J");
home();
}
void bell(int n)
{
int i;
for ( i=0; i<n; i++)
printf("%c", 7);
}
int main(void)
{
clear();
printf("Das ist links oben !\n");
store_cursor();
cursor(2,2); printf("2,2");
color(1,1);
cursor(22,22); printf("22,22");
(void)getchar();
reset_cursor();
colour(32,40,7);
printf("ENDE");
color(30,42);
(void)getchar();
bell(5);
normal();
return 0;
}
Beispiel 2:
Realisierung einiger Funktionen zur Arbeit mit Bildschirm und Cursor - Variante 2
#include <stdio.h>
void home(void)
{
printf("\033[1;1H");
}
void cursor(unsigned zeile, unsigned spalte)
{
printf("\033[%02d;%02dH", zeile, spalte);
}
void store_cursor(void)
{
printf("\033[s");
}
void reset_cursor(void)
{
printf("\033[u");
}
void color(unsigned bg, unsigned fg)
{
printf("\033[%02d;%02dm", bg, fg);
}
void colour(unsigned bg, unsigned fg, unsigned fmt)
{
printf("\033[%02d;%02d;%1dm", bg, fg, fmt);
}
void normal()
{
printf("\033[0m");
}
void clear(void)
{
printf("\033[2J\033[1;1H");
}
void bell(int n)
{
int i;
for ( i=0; i<n; i++)
printf("\a");
}
int main(void)
{
/* analog wie bei Variante 1 */
}
Variante 2 ist im Vergleich zur Variante 1 effektiver programmiert, der Quelltext ist jedoch schwerer zu lesen.
Beispiel 3:
Realisierung einiger Makros zur Arbeit mit Bildschirm und Cursor
#include <stdio.h>
#define HOME printf("\033[1;1H")
#define STORE_CURSOR printf("\033[s")
#define RESET_CURSOR printf("\033[u")
#define NORMAL printf("\033[0m")
#define CLEAR printf("\033[2J\033[1;1H")
#define CURSOR(zeile,spalte) printf("\033[%02d;%02dH", zeile, spalte)
#define COLOR(bg, fg) printf("\033[%02d;%02dm", bg, fg)
#define COLOUR(bg, fg, fmt) printf("\033[%02d;%02d;%1dm", bg, fg, fmt)
#define BELL(n) do { \
int i; \
for ( i=0; i<n; i++) \
printf("\a"); \
} \
while ( 0 )
int main(void)
{
CLEAR;
printf("Das ist links oben !\n");
STORE_CURSOR;
CURSOR(2,2); printf("2,2");
COLOR(1,1);
CURSOR(22,22); printf("22,22");
(void)getchar();
RESET_CURSOR;
COLOUR(32,40,7);
printf("ENDE");
COLOR(30,42);
(void)getchar();
BELL(5);
NORMAL;
return 0;
}
Die Anwendung von Makros anstelle von Funktionen führt noch einmal zu effektiverem Code. Funktionen bieten jedoch einen besseren Schutz gegenüber falscher Anwendung als Makros !
Vergleich der Programmgrößen
AIX xlc AIX gcc
Beispiel 1 5462 6920
2 4910 6348
3 4006 4850
Language/C 2012. 3. 16. 16:54
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <procinfo.h>
#include <sys/time.h>
#include <sys/procfs.h>
/* Macro to hide time maths */
#define TIMED(member) ((double)(procs[i].member.tv_sec+ procs[i].member.tv_usec/1000000.0))
/*
int getprocs64 ( struct procentry64 *ProcessBuffer, int ProcessSize, struct fdsinfo64 *FileBuffer, int FileSize, pid_t *IndexPointer, int Count);
*/
main(int argc, char **argv)
{
pid_t firstproc = (pid_t)0;
struct procentry64 *procs;
struct psinfo ps;
int actual_processes;
int initial_processes;
int i;
char filename[64];
int fd;
int count;
firstproc = 0;
initial_processes = getprocs64(NULL, 0, NULL, 0, &firstproc, 999999);
procs = malloc( initial_processes * sizeof(struct procentry64) );
firstproc = 0; /* you have to reset this every time */
actual_processes = getprocs64(procs, sizeof(struct procentry64), NULL, 0, &firstproc, initial_processes);
printf("PID,CPU-Time,Memory,Threads,Status,Start,UID,Command,CMD-Arguments\n");
for(i=0;i<actual_processes;i++) {
sprintf(ps.pr_psargs, "data missing", 12);
sprintf(filename, "/proc/%d/psinfo", procs[i].pi_pid);
/*printf("opening file %s\n",filename);*/
fd=open(filename, O_RDONLY);
if(fd == -1) {
perror("open failure");
} else {
count = read(fd,&ps,sizeof(struct psinfo));
if(count != sizeof(struct psinfo)) {
perror("read failure");
printf("count was %d expected %d\n", count, sizeof(struct psinfo));
}
close(fd);
}
/* patch up weird commands */
if(procs[i].pi_pid == 0) strcpy(procs[0].pi_comm, "Swapper");
if(procs[i].pi_state == SZOMB)
strcpy(procs[i].pi_comm, "><defunct Zombie>");
if(!strcmp("gil", procs[i].pi_comm))
strcpy(procs[i].pi_comm, "gil = TCP/IP");
printf("%d,%0.0f,%d,%d,%d,%d,%d,%s,%s\n",
(int)procs[i].pi_pid,
(double) (TIMED(pi_ru.ru_utime) +TIMED(pi_ru.ru_stime)),
(int)procs[i].pi_size*4, /* convert pages to KBytes */
(int)procs[i].pi_thcount,
(int)procs[i].pi_state,
(int)procs[i].pi_start,
(int)procs[i].pi_uid,
procs[i].pi_comm,
ps.pr_psargs
);
}
}
=========================================================================================================
#include <stdio.h>
#include <stdlib.h>
#include <procinfo.h>
#include <sys/types.h>
int
main(argc, argv)
int argc;
char *argv[];
{
struct procentry64 psinfo;
pid_t pid;
if (argc > 1)
pid = atoi(argv[1]);
else
pid = getpid();
printf("My pid: %d\n", pid);
if (getprocs64(&psinfo, sizeof(struct procentry64), NULL, sizeof(struct fdsinfo64) , &pid, 1) > 0) {
printf("Pid: %d\n", psinfo.pi_pid);
printf("Up start: %lld\n", psinfo.pi_start);
printf("Program name: %s\n", psinfo.pi_comm);
return 0;
} else {
perror("getproc64");
return 1;
}
}
Language/C 2012. 3. 15. 15:51
fork()함수
프로그램내 동작하고 있는 프로세스를 복사하고 복사한 프로세스를 독립적으로 돌려주는 함수입니다 흔히 원복 프로세서를 부모프로세스라 부르고 복사한 프로세스를 자식프로세스라 부릅니다.
헤더 unistd.h
형태 pid_t fork(void);
반환 pid_t 실행에 실패하면 -1 을 반환. 부모에게는 새로 생성된 자식 프로세스 PID가 반환되며, 자식 프로세스에는 0이 반환됩니다.
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int global_var = 0;
int main()
{
pid_t ret_pid, child;
int local_var = 0;
ret_pid = fork();
if(ret_pid < 0)
{
printf("fork() error\n");
return -100;
}
else if(ret_pid == 0)
{
global_var++;
local_var++;
printf("CHILD - my PID : %d parents PID : %d \n", getpid(),getppid());
}
else
{
sleep(10);
global_var += 5;
local_var += 5;
printf("PARENT - my pid : %d chail's PID : %d\n", getpid(),ret_pid);
}
printf("\t global_var : %d \n",global_var);
printf("\t local_var : %d \n",local_var);
return 0;
}
결과>>
좀비 프로세스
- 프로세스 종료 후 메모리상에서 사라지지 않은 프로세스
좀비 프로세스 생성 이유
- 자식 프로세스가 종료하면서 반환된 값 0을 커널이 부모 프로세스에 전달한 후 자식
프로세스를 소멸시킴.
- 반환값을 부모 프로세스에 전달하지 못한 경우 자식 프로세스는 좀비로 존재.
- 부모 프로세스가 커널에게 종료된 자식 프로세스의 리턴값을 전달 요청을 해야만
커널이 리턴값 전달 가능함
종료된 자식 프로세스의 리턴값 요청 함수
1. wait 함수
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int * status);
성공시 종료된 자식 프로세스 ID, 실패시 -1 리턴
- status : 포인터 status가 가리키는 변수에 자식 프로세스 종료시 리턴하거나
exit 함수 호출시 전달한 인자값이 저장됨
- 매크로함수 WEXITSTATUS(status)로 종료시 리턴값이나 exit() 인자로 넘겨진 값 확인
- 호출 시점에 종료된 자식 프로세스가 없으면 blocking 상태에 빠짐
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int global_var = 0;
int main()
{
pid_t ret_pid, child;
int local_var = 0;
int state;
ret_pid = fork();
if(ret_pid < 0)
{
printf("fork() error\n");
return -100;
}
else if(ret_pid == 0)
{
global_var++;
local_var++;
printf("CHILD - my PID : %d parents PID : %d \n", getpid(),getppid());
}
else
{
global_var += 5;
local_var += 5;
printf("PARENT - my pid : %d chail's PID : %d\n", getpid(),ret_pid);
child = wait(&state);
printf("\t Child PID = %d \n", child);
printf("\t return value = %d \n", WEXITSTATUS(state));
sleep(10);
}
printf("\t global_var : %d \n",global_var);
printf("\t local_var : %d \n",local_var);
return 0;
}
|
결과>>
2. waitpid 함수 (wait함수의 blocking 상태 해결)
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int * status, int options);
성공시 종료된 자식 프로세스ID(경우에 따라 0), 실패시 -1 리턴
- pid : 종료 확인을 원하는 자식 프로세스 ID. 임의의 자식 프로세스인 경우 -1 대입.
- status : wait 함수의 status와 같은 역할
- options : sys/wait.h에 정의된 ‘WNOHANG’ 상수를 인자로 전달하게 되면 이미 종료한
자식 프로세스가 없는 경우 blocking 상태로 가지않고 바로 리턴함.
이때 waitpid 함수의 리턴값은 0이 된다.
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int global_var = 0;
int main()
{
pid_t fork_ret, child;
int local_var = 0;
int state;
fork_ret = fork();
if(fork_ret < 0)
{
printf("fork() error\n");
exit(1);
}
else if(fork_ret == 0)
{
global_var++;
local_var++;
printf(" CHILD - my PID : %d parent's PID : %d \n", getpid(),getppid());
sleep(10);
}
else
{
global_var += 5;
local_var += 5;
printf("PARENT - my PID : %d child's PID : %d \n", getpid(),fork_ret);
do
{
sleep(3);
puts("3초 대기");
child = waitpid(-1, &state, WNOHANG);
}
while(child == 0);
printf("\t 종료된 자식 프로세스 ID = %d \n", child);
printf("\t 종료된 자식 프로세스의 리터 값 = %d \n", WEXITSTATUS(state));
}
printf("\t global_var : %d \n", global_var);
printf("\t local_var : %d \n", local_var);
return 0;
}
|
결과>>
waitpid 함수의 호출 시점은??
- 자식 프로세스가 종료되는 순간 부모 프로세스가 waitpid 함수를 호출하도록 해야함
- 자식 프로세스가 종료된 시점에 발생하는 시그널 SIGCHLD를 이용
- sigaction 함수를 사용하여 SIGCHLD가 발생시 부모 프로세스가 자식 프로세스의 리턴
값을 읽도록 함
좀비 프로세스확인
결과>> wait함수 실행시 ps -u를 입력하여 확인합니다
STAT의 Z가 zombie를 뜻합니다
STAT에 Z가 없는 것을 확인 할 수 있습니다
시그널(SIGCHLD)의 이용
SIGCHLD : (시그널무시)자식프로세서 종료
sigemptyset() 주어진 마스크 셋의 모든 필드를 설정하거나 헤제한다
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
void z_handler();
int global_var = 0;
int main()
{
pid_t fork_ret, child;
int local_var = 0;
int state;
struct sigaction act;
act.sa_handler = z_handler;
sigemptyset(&act.sa_mask);
act.sa_flags =0;
state = sigaction(SIGCHLD, &act,0);
if(state != 0)
{
puts("sigaction() error\n");
exit(1);
}
fork_ret = fork();
if(fork_ret < 0)
{
printf("fork() error\n");
exit(1);
}
else if(fork_ret == 0)
{
global_var++;
local_var++;
printf(" CHILD - my PID : %d parent's PID : %d \n", getpid(),getppid());
}
else
{
global_var += 5;
local_var += 5;
printf("PARENT - my PID : %d child's PID : %d \n", getpid(),fork_ret);
sleep(5);
}
printf("\t global_var : %d \n", global_var);
printf("\t local_var : %d \n", local_var);
return 0;
}
void z_handler()
{
pid_t child;
int state;
child = waitpid(-1, &state, WNOHANG);
printf("\t 소멸된 자식 프로세스 ID = %d \n", child);
printf("\t 소멸된 자식 프로세스의 리턴 값 = %d \n", WEXITSTATUS(state));
} |
결과>>
**정상적으로 자식프로세스가 종료된것을 확인 할 수있습니다
Language/C 2012. 3. 14. 19:50
strerror
#include <string.h> // C++ 에서는 <cstring>
char * strerror ( int errnum );
오류 메세지 문자열을 가리키는 포인터를 얻어온다. errnum 의 값을 통해 발생하였던 오류에 알맞은 오류 메세지를 가리키는 포인터를 리턴한다. 이 때 리턴되는 포인터는 문자열 리터럴을 가리키고 있기 때문에 그 내용이 바뀔 수 없다. 참고로 strerror 에 의해 출력되는 오류 메세지는 현재 사용중인 컴파일러나 플랫폼에 따라 다를 수 있다.
errnum오류 번호
오류 번호에 해당하는 오류 문자열을 가리키는 포인터
이 함수는 C 표준 함수 중에서 이름에 r 이 가장 많이 포함되어 있는 함수 이다. 무려 r 이 4 개나 있다.
/*
존재하지 않는 파일 unexist.ent 를 열라고 해 오류가 발생한다. 이 예제는 http://www.cplusplus.com/reference/clibrary/cstring/strerror/ 에서 가져왔습니다.
*/ #include <stdio.h> #include <string.h> #include <errno.h>
int main () { FILE * pFile; pFile = fopen ("unexist.ent","r"); if (pFile == NULL) printf ("Error opening file unexist.ent: %s\n",strerror(errno)); return 0; }
Language/C 2012. 3. 9. 22:13
#include <stdlib.h>
void *bsearch( const void *key,
const void *base,
size_t nmemb,
size_t size,
int (*compar)(const void *, const void *));
Parameters :
key : 찾고자 하는 키 값(Target)
base : 찾을 대상이 있는 Array Object의 주소
nmemb : array element 개수
size : array element 하나의 byte size
compar : 비교함수. 각각 두 개의 파라미터는 key와 하나의 array element를 가리키는 주소값이다.
자세한 내용은 Description 참조.
Return Value :
함수 실행 결과, 매칭하는 Array Object의 주소값을 리턴한다.
매칭되는 결과값이 없는 경우는 NULL을 리턴한다.
Description :
bsearch()함수는 binary search를 수행한다.
물론 직접 binary search 알고리즘을 구현할 수도 있겠지만 구태여 그렇게 힘들일 필요 없다.
다 만들어서 제공해주고 있으니 만들어준 사람 성의를 생각해서 그냥 잘 가져다 쓰면 된다!
※ 비교함수(compar)
key 파라미터와 array element를 비교하여 key 값이 더 작으면 음수, 같으면 0, 더 크면 양수를 리턴한다.
실제 프로그래밍시 비교함수는 직접 코딩해줘야한다.
<비교함수 코딩 예>
static int compare(const void *key, const void *data) {
return *(int *)key - *(int *)data;
}
위의 비교함수를 이용하여 bsearch()함수를 호출할 때는 이렇게 하면 된다.
int *d = (int *d)bsearch(&key, data, sizeof data / sizeof(int), sizeof(int), compare);
bsearch 알고리즘:
lsearch()나 lfind()가 테이블의 첫번째 요소부터 마직막 요소까지 하나씩 데이터를 검색한다면 bsearch()는 이진 검색으로 매우 빠르게 자료를 검색할 수 있습니다.
그러나 이진 검색을 하기 위해서는 반드시 테이블의 자료는 정령되어 있어야 합니다. 왜 이진 검생르 위해 테이블이 정렬되어 있어야 하는지 이유를 보겠습니다.
지금 테이블에 1에서 10까지 데이터가 차례로 정렬되어 있습니다.
1 |
21 |
32 |
43 |
54 |
65 |
76 |
87 |
98 |
190 |
이 테이블에서 98을 찾아 보겠습니다. 우선 전체 테입블 요소 중 가운데에 해당하는 다섯번째 데이터와 비교합니다.
1 |
21 |
32 |
43 |
54 |
65 |
76 |
87 |
98 |
190 |
가운데 요소와 비교했더닌 검색하려는 데이터 98보다 작습니다. 그러므로 1부터 43까지는 검색할 필요가 없습니다.
이번에는 5 번째 요소와 10번째 요소의 가운데 요소인 8번째 요소와 비교합니다.
1 |
21 |
32 |
43 |
54 |
65 |
76 |
87 |
98 |
190 |
역시 찾으려는 98보다 작습니다. 이번에는 8 번째와 10 번째의 가운데에 해당하는 9 번째와 비교하게 됩니다.
1 |
21 |
32 |
43 |
54 |
65 |
76 |
87 |
98 |
190 |
lsearch()와 lfind()는 첫번째 요소부터 차례로 검색하기 때문에 9번이나 비교해야 하지만 bsearch 는 이와 같이 정렬된 자료에서 이분화해서 검색하므로 단 3번의 비교로 자료를 검색할 수 있습니다.
그러므로 매우 많은 자료에서는 이진 검색인 bsearch()가 매우 빠르게 검색할 수 있습니다.
Language/C 2012. 2. 2. 14:00
설명
semget() 함수는 세마포어 집합을 생성하거난 이미 생성된 세마포어에 접근하기 위해 사용합니다.
세마포어는 공유 자원을 동시에 여러 프로세스가 사용하는 것을 막고, 오직 자원을 하나의 프로세스만 사용할 수 있도록 보장해 주는 방법입니다. 즉, 여러 프로세스 중 공유 자원을 자신이 사용할 수 있는지 있다면 작업이 끝나기 전까지 다른 프로세스가 공유 자원을 사용할 수 없도록 다른 프로세스의 접근을 제어하는 방법을 세마포어를 이용하여 구현할 수 있습니다.
세마포어를 제일 간단히 설명한다면 특정 변수를 두고, 이 변수를 미리 확인합니다. 특정 변수를 확인하는 함수를 p()라고 하겠습니다.
- 프로세스는 공유자원을 사용하기 전에 p()함수를 호출합니다.
- p()는 특정 변수 값을 확인하여 공유 자원이 다른 프로세스가 사용 중인지의 여부를 판단하고, 다른 프로세스가 사용 중이면 그 프로세스가 사용을 중지할 때까지 대기합니다. 공유 자원이 사용 가능하다면 특정 변수값을 변경하고 복귀합니다.
- 프로세스는 공유 자원을 사용합니다.
- 프로세스는 공유 자원에 대한 작업을 완료했다면 s() 함수를 호출하여 특정 변수값을 원래의 값으로 복원합니다.
이렇게 프로세스가 s() 함수를 호출하여 변수값을 원래 값으로 변경하면 다른 프로세스의 p()함수는 공유 자원의 사용이 가능하다고 판단하게 됩니다.
헤더 |
sys/types.h
sys/ipc.h
sys/sem.h |
형태 |
int semget ( key_t key, int nsems, int semflg ) |
인수 |
key_t key |
시스템에서 세머포어를 식별하는 집합 번호 |
int nsems |
세마포어 집합 내의 세마포어 개수로 접급 제한하려는 자원의 개수 |
int semflg |
동작 옵션
semflg |
옵션 내용 |
IPC_CREATE |
key에 해당하는 공유 세머포어가 없다면 새로 생성한다. 만약있다면 무시하며 생성을 위해 접근 권한을 지정해 주어야 한다. |
IPC_EXCL |
세머포어가 이미 있다면 실패로 반환하며 세머포어에 접근하지 못한다. 이 옵션이 없어야 기존 세마포어를 사용할 수 있다. |
|
|
반환 |
-1 |
실패 |
-1 이외 |
새로 만들어진 세마포어 식별자 또는 key 와 일치하는 세마포어 식별자 |
|
예제
아래의 예제에서는 두개의 쓰레드를 만들어 하나의 자원인 카운터 cnt 를 서로 방해하지 않고 사용하는 모습을 보여 주고 있습니다.
#include<pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int cnt = 0;
static int semid;
void p()
{
struct sembuf pbuf;
pbuf.sem_num = 0;
pbuf.sem_op = -1;
pbuf.sem_flg = SEM_UNDO;
if ( -1 == semop(semid, &pbuf, 1))
printf( "p()-semop() 실행 오류\n");
}
void v()
{
struct sembuf vbuf;
vbuf.sem_num = 0;
vbuf.sem_op = 1;
vbuf.sem_flg = SEM_UNDO;
if ( -1 == semop( semid, &vbuf, 1))
printf( "v()-semop() 실행 오류\n");
}
void *fun_thread1(void *arg)
{
while( cnt < 5)
{
p();
printf( "thread1 실행\n");
cnt++;
usleep( 100);
printf( "thread1 종료\n");
v();
}
return NULL;
}
void *fun_thread2(void *arg)
{
while( cnt < 5)
{
p();
printf( "thread2 실행\n");
printf( "카운터= %d\n", cnt);
usleep( 100);
printf( "thread2 종료\n");
v();
}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t thread1;
pthread_t thread2;
union semun{
int val;
struct semid_ds *buf;
unsigned short int *arrary;
} arg;
if ( -1 == (semid = semget( IPC_PRIVATE, 1, IPC_CREAT ¦ 0666)))
{
printf( "semget() 실행 오류\n");
return -1;
}
arg.val = 1; // 세마포어 값을 1로 설정
if ( -1 == semctl(semid, 0, SETVAL, arg))
{
printf( "semctl()-SETVAL 실행 오류\n");
return -1;
}
pthread_create(&thread1, NULL, fun_thread1, NULL);
pthread_create(&thread2, NULL, fun_thread2, NULL);
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
if ( -1 == semctl(semid, 0, IPC_RMID, arg))
{
printf( "semctl()-IPC_RMID 실행 오류\n");
return -1;
}
printf( "프로그램 종료\n");
return 0;
}
]$ ./a.out
a
]$
Language/C 2012. 2. 2. 12:43
32비트에 컴파일할 때 문제가 없던 일들이..
64비트에서 일어난 경우 중 하나입니다.
inet_ntoa() 이 함수
컴파일 에러는 없지만.. 이 함수가 실행하는 시점에서 Segment fault 라는 메시지를 접하실겁니다.
해결방법은..
간단히 헤더에 한줄만 추가해주면됩니다.
#include <arpa/inet.h>
그리고 기존에 아래와 같이 코딩하고 계셨다면..
printf("%s ", inet_ntoa(ip->saddr));
아래와 같은 에러를 접하셨을겁니다.
error: incompatible type for argument 1 of ‘inet_ntoa’
간단히 해석해보면 inet_ntoa() 함수의 인자값이 잘못된다는 얘기입니다
아래와 같이 수정하시면 해결이 됩니다.
printf("%s ", inet_ntoa(*(struct in_addr *)&ip->saddr));
Language/C 2012. 1. 30. 17:04
char fname[32]="/log/test.log";
FILE *debug;
debug = fopen(fname, "a+");
fprintf(debug, "%s\n","test");
fflush(debug);
fclose(debug);
|