-
20140625 (메시지 큐 우선순위, 공유 메모리)부산IT학원/스마트컨트롤러 2014. 6. 25. 12:30
88일차
----------------------
메시지 큐 우선순위
----------------------
--- 메시지가 처리될 때 우선순위를 정할 수도 있다.
예제 소스)
26_3.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <sys/types.h>
4 #include <sys/ipc.h>
5 #include <sys/msg.h>
6
7 #define SIZE 124
8
9 struct
10 {
11 long type;
12 char data[SIZE];
13 }msg_data;
14
15 int main()
16 {
17 int msqid;
18 int data_len;
19 char buffer[SIZE];
20
21 if((msqid = msgget((key_t)7878, IPC_CREAT |0666)) == -1)
22 {
23 perror("msgget failed");
24 exit(1);
25 }
26
27 while(1)
28 {
29 printf("input data => ");
30 scanf("%s", buffer);
31 fflush(stdin);
32
33 if(!strcmp(buffer, "quit"))
34 {
35 break;
36 }
37
38
39 printf("input priority -> ");
40 scanf("%ld", &(msg_data.type));
41 fflush(stdin);
42 strcpy(msg_data.data, buffer);
43
44 if(msgsnd(msqid, &msg_data, strlen(msg_data.data), 0) == -1)
45 {
46 perror("msgsnd failed");
47 exit(1);
48 }
49 }
50 return 0;
51 }26_4.c
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/ipc.h>
4 #include <sys/msg.h>
5 #include <errno.h>
6
7 #define SIZE 124
8 #define PRIOR 10
9
10 struct
11 {
12 long type;
13 char data[SIZE];
14 }msg_data;
15
16 int main()
17 {
18 int msqid;
19 int data_len;
20
21 if((msqid = msgget((key_t)7878, IPC_CREAT |0666)) == -1)
22 {
23 perror("msgget failed");
24 exit(1);
25 }
26
27 while(1)
28 {
29 if((data_len = msgrcv(msqid, &msg_data, SIZE, (-1*PRIOR), IPC_NOWAIT)) == -1)
30 {
31 if(errno == ENOMSG)
32 {
33 printf("no messgae\n");
34 break;
35 }
36
37 perror("msgrcv failed");
38 break;
39 }
40
41 msg_data.data[data_len] = 0;
42 printf("data : %s [%ld]\n", msg_data.data, msg_data.type);
43 }
44
45 if(msgctl(msqid, IPC_RMID, 0) == -1)
46 {
47 perror("msgctl failed");
48 exit(1);
49 }
50
51 return 0;
52 }
53실행화면
-----------------
공유 메모리
-----------------
--- 공유 메모리
공유 메모리란 여러 프로세스가 함께 이용할 수 있는 메모리를 말한다.
모든 프로세스 전역변수? 같은 역할이다.
공유메모리를 사용할 때에는
1. 생성
2. 첨부
3. 분리
4. 제거
과정을 거친다.
공유 메모리를 가져와서 바로 쓸 수 있는게 아니라
공유 메모리를 자신의 메모리인 마냥 첨부 시켜야 한다고 한다.
다 사용 후 분리를 시켜주고 제거하거나 한다.
--- shmget
공유 메모리 생성
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, int size, int shmflg);
key : 시스템에서 식별하는 공유 메모리 번호
size : 공유 메모리 크기
shmflg : 동작 옵션
IPC_CREAT : key에 해당하는 공유 메모리가 존재하지 않으면 생성하는데 접근 권한도 함께
부여해야 한다. 만약 공유 메모리가 있으면 이 옵션은 무시.
IPC_EXCL : 공유 메모리가 있으면 실패로 -1을 반환. 이 값이 설정되지 않으면 기존 공유
메모리에 접근하여 식별자를 반환한다.
리턴값
성공시
공유 메모리 식별자
실패시
-1
--- shmat
공유 메모리를 호출 프로세스 메모리로 첨부
(공유 메모리는 자신의 메모리에 첨부해야만 자신의 메모리인 것처럼 사용 가능하다)
#include <sys/types.h>
#include <sys/shm.h>
void * shmat(int shmid, const void * shmaddr, int shmflg);
shmid : 공유 메모리 식별자
shmaddr : 공유 메모리 주소, 일반적으로 NULL
shmflg : 동작 옵션
SHM_RDONLY : 읽기 전용으로 사용
SHM_RND : shmaddr을 NULL
리턴값
성공시
공유 메모리 주소 포인터
실패시
(void *)-1
--- shmdt
공유 메모리를 호출 프로세스 메모리에서 분리한다.
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void * shmaddr);
shmaddr : 삭제할 공유 메모리 주소
리턴값
성공시
0
실패시
-1
--- shmctl
공유 메모리 제어한다.
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds * buf);
shmid : 공유 메모리 식별자
cmd : 제어 종류
IPC_STAT : 공유 메모리의 정보를 얻어 buf에 저장.
IPC_SET : 공유 메모리의 정보를 buf에 저장한 값으로 변경한다. 단, shm_perm과 shm_ctime멤버에
대한 정보만 변경할 수 있다.
IPC_RMID : 공유 메모리를 제거. 이 때 세 번째 인수 buf는 0으로 지정.
buf : 공유 메모리 정보에 대한 포인터
struct shmid_ds
{
struct ipc_perm shm_perm; // 접근 권한
int shm_segsz; // 세그먼트 크기(바이트)
time_t shm_atime; // 최종 접근 시간
time_t shm_dtime; // 최종 제거 시간
time_t shm_ctime; // 최종 변경 시간
unsigned short shm_cpid; // 생성 프로세스의 PID
unisgned short shm_lpid; // 최종적으로 동작한 프로세스의 PID
short shm_nattch; // 현재 접근한 프로세스의 수
unsigned short shm_npages; // 세그먼트의 크기(페이지)
unsigned long * shm_pages; // 페이지 테이블 항목을 위한 필드
struct shm_desc * attaches; // 접근을 위한 기술자들
};
리턴값
성공시
0
실패시
-1
예제 소스)
26_5.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <sys/types.h>
4 #include <sys/ipc.h>
5 #include <sys/shm.h>
6 #include <signal.h>
7
8 #define SIZE 1024
9
10 void signalHandler(int signo);
11 int shmid;
12
13 int main()
14 {
15 void *shmaddr;
16
17 if((shmid = shmget((key_t)7878, SIZE, IPC_CREAT | 0666)) == -1)
18 {
19 perror("shmid failed");
20 exit(1);
21 }
22
23 if((shmaddr = shmat(shmid, (void*)0, 0)) == (void *) -1)
24 {
25 perror("shmat failed");
26 exit(1);
27 }
28
29 strcpy((char*)shmaddr, "Linux Programming");
30
31 if(shmdt(shmaddr) == -1)
32 {
33 perror("shmdt failed");
34 exit(1);
35 }
36
37 signal(SIGINT, signalHandler);
38 pause();
39
40 return 0;
41 }
42
43 void signalHandler(int signo)
44 {
45 if(shmctl(shmid, IPC_RMID, 0) == -1)
46 {
47 perror("shmctl failed");
48 exit(1);
49 }
50
51 exit(0);
52 }26_6.c
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/ipc.h>
4 #include <sys/shm.h>
5 #include <signal.h>
6
7 #define SIZE 1024
8
9 int main()
10 {
11 int shmid;
12 void *shmaddr;
13 struct shmid_ds shm_stat;
14
15 if((shmid = shmget((key_t)7878, SIZE, IPC_CREAT | 0666)) == -1)
16 {
17 perror("shmid failed");
18 exit(1);
19 }
20
21 if((shmaddr = shmat(shmid, (void*)0, 0)) == (void *) -1)
22 {
23 perror("shmat failed");
24 exit(1);
25 }
26
27 printf("data read from shared memory : %s\n", (char *)shmaddr);
28
29 if(shmctl(shmid, IPC_STAT, &shm_stat) == -1)
30 {
31 perror("shmctl failed");
32 exit(1);
33 }
34
35 if(shmdt(shmaddr) == -1)
36 {
37 perror("shmdt failed");
38 exit(1);
39 }
40
41 kill(shm_stat.shm_cpid, SIGINT);
42
43 return 0;
44 }실행화면
------------
세마포어
------------
--- 세마포어?
세마포어란 여러 프로세스들이 한정된 자원을 사용할 때,
한정된 수의 프로세스만 사용할 수 있게 해주는 방법이다.
--- semget
세마포어 집합을 생성.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
key : 세마포어 ID
nsems : 생성할 세마포어 방 갯수
semflg : 옵션
IPC_CREAT : key에 해당하는 세마포어 ID가 없으면 접근 권한과 함께 생성.
없으면 무시.
IPC_EXCL : 세마포어 ID가 있으면 실패로 -1, 이 값을 설정해 주지 않으면
기존 세마포어 ID에 접근하여 ID를 반환한다.
리턴값
성공시
세마포어 ID
실패시
-1
--- semctl
세마포어 제어
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, union semun arg);
semid : 세마포어 ID
semnum : 세마포어 내에 제어할 세마포어 방 번호
0 이면 첫 번째 세마포어
1 이면 두 번째 세마포어
2 이면 세 번째 세마포어를 지칭한다.
cmd : 제어
GETVAL 세마포어의 현재 값을 구한다.
GETPID 세마포어에 가장 최근에 접근했던 프로세스의 프로세스 ID를 구한다.
GETNCNT 세마포어 값이 증가하기를 기다리는 프로세스의 개수
GETZCNT 세마포어 값이 0 이 되기를 기다리는 프로세스의 개수
GETALL 세마포어 집합의 모든 세마포어 값을 구한다.
SETVAL 세마포어 값을 설정
SETALL 세마퍼어 집합의 모든 세마포어 값을 설정
IPC_STAT 세마포어의 정보를 구한다.
IPC_SET 세마포어의 소유권과 접근 허가를 설정
IPC_RMID 세마포어 집합을 삭제
arg : cmd에 따라 다른 옵션
리턴값
성공시
0 이상 양수
실패시
-1
--- semop
세마포어 연산
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf * sops, unsigned nsops);semid : 세마포어 IDsops : 연산할 내용struct sembuf{short sem_num;short sem_op;short sem_flg;};sem_flgIPC_NOWAIT : 호출 즉시 실행하지 못할 경우 기다리지 않고 실패로 -1 리턴IPC_UNDO : 프로세스가 종료되면 세마포어 설정을 원래 상태로 되돌린다.예기치 못한 종료에 세마포어를 원상복귀 시키지 못할 경우라도 복귀해 주기때문에 설정해 주는 것이 좋다.nsops : 연산할 갯수한 번 계산하면 1두 번 계산하면 2보통 1이겠지?리턴값성공시0실패시-1예제 소스)
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/types.h>
4 #include <sys/ipc.h>
5 #include <sys/sem.h>
6
7 void repeat(int semid);
8 void p(int semid);
9 void v(int semid);
10
11 main()
12 {
13 int semid, i;
14 union semun {
15 int val;
16 struct semid_ds *buf;
17 unsigned short int *array;
18 } arg;
19
20 // 세마포어가 1개인 8877 키의 세마포어 집합 생성
21 if((semid=semget((key_t)8877, 1, IPC_CREAT|0666)) == -1) {
22 perror("semget failed");
23 exit(1);
24 }
25
26 // 세마포어 값을 1로 설정
27 arg.val = 1;
28 if(semctl(semid, 0, SETVAL, arg) == -1) {
29 perror("semctl failed");
30 exit(1);
31 }
32
33 // 3개의 자식 프로세스 생성
34 for(i=0; i<3; i++) {
35 if(!fork())
36 repeat(semid);
37 }
38
39 // 10초간 정지
40 sleep(10);
41
42 // semid 세마포어 삭제
43 if(semctl(semid, 0, IPC_RMID, arg) == -1) {
44 perror("semctl failed");
45 exit(1);
46 }
47 exit(0);
48 }
49
50 void repeat(int semid)
51 {
52 // 난수 초기화하기
53 srand((unsigned int)getpid());
54 p(semid);
55
56 // getpid()는 현재 프로세스의 프로세스 ID를 반환
57 printf("%d process is using tool\n", getpid());
58
59 // 난수를 5로 나눈 나머지 초 동안 정지
60 sleep(rand()%5);
61 printf("%d process is returning tool\n", getpid());
62 v(semid);
63
64 exit(0);
65 }
66
67 void p(int semid)
68 {
69 struct sembuf pbuf;
70
71 pbuf.sem_num = 0;
72 pbuf.sem_op = -1;
73
74 // 프로세스 종료하면 세마포어 설정 원상 복귀
75 pbuf.sem_flg = SEM_UNDO;
76
77 // 현재 세마포어 값인 semval 1 감소하기
78 if(semop(semid, &pbuf, 1) == -1) {
79 perror("semop failed");
80 exit(1);
81 }
82 }
83
84 void v(int semid)
85 {
86 struct sembuf vbuf;
87 vbuf.sem_num = 0;
88 vbuf.sem_op = 1;
89 vbuf.sem_flg = SEM_UNDO;
90 // 현재 세마포어 값인 semval 1 증가하기
91 if(semop(semid, &vbuf, 1) == -1) {
92 perror("semop failed");
93 exit(1);
94 }
95 }------------
select 함수
------------
--- select
파일 디스크립터들의 읽기, 쓰기, 오류를 감시한다.
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int n, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZERO(fd_set *set);
fd_set
http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/system_programing/File/select
'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20140701 (ARM Cygwin, arm-gcc) (0) 2014.07.01 20140626 (select, 1:1 채팅) (0) 2014.06.26 20140624 (레코드 잠금, 파이프 통신, 메시지 큐) (0) 2014.06.24 20140623 (pthread, 레코드 잠금) (0) 2014.06.23 20140620 (시그널, 멀티쓰레드) (0) 2014.06.20