QNX---지식 채널(Channel) 및 연결(Connect)
4568 단어 QNX 시스템 및 드라이브
QNX 채널의 개념:
채널(Channel) 및 연결(Connect)
메시지 전달은 서버와 클라이언트의 모델을 바탕으로 이루어진다. 그러면 클라이언트는 어떻게 해야만 서버 측과 통신할 수 있습니까?가장 간단한 것은 당연히 상대방의 프로세스 번호를 지정하는 것이다.보낼 쪽은 메시지를 헤더로 붙여서'이 메시지를 pid12345에 보내주세요'라고 안쪽에 알려주면 됩니다.사실 이것도 QNX4의 방법이다.그러나 QNX6가 POSIX 라인을 완전히 지원하기 시작하면 이런 방법은 그다지 적합하지 않은 것 같다.만약 서버가 두 개의 라인을 가지고 각각 다른 서비스를 진행한다면 어떻게 해야 합니까?아니면 "이 소식을 pid 12345tid 3에 보내주세요"라고 말하면 됩니다.그러나 만약에 어떤 서비스가 단일 라인에서 서비스를 하는 것이 아니라 한 조의 라인에서 진행된다면 어떻게 하겠는가?이를 위해 QNX6는'채널'(Channel)이라는 개념을 추상화했다. 하나의 채널은 하나의 서비스의 입구이다. 이 채널이 도대체 얼마나 많은 라인을 서비스하는지 서버 측의 일이다. 한 서버에 여러 서비스가 있으면 여러 채널을 열 수 있다. 클라이언트는'채널'에 메시지를 보내기 전에 연결(Connection)을 만들어야 한다.그리고 메시지를 연결에 보냅니다.이렇게 하면 같은 클라이언트가 필요하면 같은 채널과 여러 개의 연결을 할 수 있다.
서버
코드:모두 선택 ChannelId = ChannelCreate(Flags);
ChannelId = ChannelCreate(Flags);
클라이언트
코드:모두 선택
ConnectionId = ConnectAttach(Node, Pid, Chid, Index, Flag);
Node: 기계 번호입니다. 네트워크 분포 처리가 존재하면 이 값이 그 기계를 결정합니다.서버와 클라이언트가 같은 판에 있으면 0입니다.
PID: 프로세스 번호,
CHID: 채널 번호;
일반 API 함수
extern int ChannelCreate(unsigned __flags);extern int ChannelCreate_r(unsigned __flags); extern int ChannelCreateExt(unsigned __flags, mode_t __mode, size_t __bufsize, unsigned __maxnumbuf, const struct sigevent *__ev, struct _cred_info *__cred); extern int ChannelDestroy(int __chid); extern int ChannelDestroy_r(int __chid);extern int ConnectAttach(_Uint32t __nd, pid_t __pid, int __chid, unsigned __index, int __flags); extern int ConnectAttach_r(_Uint32t __nd, pid_t __pid, int __chid, unsigned __index, int __flags); extern int ConnectAttachExt(_Uint32t __nd, pid_t __pid, int __chid, unsigned __index, int __flags, struct _asyncmsg_connection_descriptor *__cd); extern int ConnectDetach(int __coid);
extern int ConnectDetach_r(int __coid);
extern int MsgReceive(int __chid, void *__msg, int __bytes, struct _msg_info *__info);
extern int MsgReceive_r(int __chid, void *__msg, int __bytes, struct _msg_info *__info);
extern int MsgReply(int __rcvid, int __status, const void *__msg, int __bytes);
extern int MsgReply_r(int __rcvid, int __status, const void *__msg, int __bytes);
extern int MsgRead(int __rcvid, void *__msg, int __bytes, int __offset); extern int MsgRead_r(int __rcvid, void *__msg, int __bytes, int __offset);
연결의 끝은 ConnectDetach()이고 채널의 끝은 ChannelDestroy()입니다.그러나 일반적으로 서버는 오래 존재하기 때문에 ChannelDestroy()가 필요하지 않습니다.
전송(Send), 수신(Receive), 응답(Reply) QNX의 메시지 전달은 우리가 전통적으로 흔히 볼 수 있는 프로세스 간의 통신과 가장 큰 차이점은 바로 이것이'동기적'메시지 전달이다.하나의 메시지 전달은 모두 발송, 수신과 응답의 세 부분, 이른바 SRR 과정을 거쳐야 한다.구체적으로 말하면 클라이언트가 연결에서'발송'메시지를 보내면 클라이언트가 막히고 서버 측이 메시지를 수신하여 처리하며 마지막으로 처리 결과를'응답'클라이언트에게 한다.서버가 응답해야 클라이언트의 차단 상태가 해제됩니다.이런 동기화 과정은 클라이언트와 서버 측의 시퀀스를 보장할 뿐만 아니라 프로그래밍도 크게 간소화시켰다.구체적으로 API로 말하자면 이렇다.
#include
#include #include #include #include #include #define MY_PULSE_CODE _PULSE_CODE_MINAVAIL typedef union { struct _pulse pulse; /* your other message structures would go here too */} my_message_t; int main(int argc, char *argv[]) { struct sigevent event; struct itimerspec itime; timer_t timer_id; int chid; int rcvid; my_message_t msg; chid = ChannelCreate(0);/*채널 */이벤트를 만듭니다.sigev_notify = SIGEV_PULSE; event.sigev_coid = ConnectAttach(ND_LOCAL_NODE, 0, chid, _NTO_SIDE_CHANNEL, 0); event.sigev_priority = getprio(0); event.sigev_code = MY_PULSE_CODE; timer_create(CLOCK_REALTIME, &event, &timer_id); /*it_value 설정은 첫 번째 초기화 값 */itime입니다.it_value.tv_sec =1; /* 500 million nsecs = .5 secs */ itime.it_value.tv_nsec = 500000000; /*it_interval은 매번 간격값 */itime를 설정합니다.it_interval.tv_sec = 0; /* 500 million nsecs = .5 secs */ itime.it_interval.tv_nsec = 100000000; timer_settime(timer_id, 0, &itime, NULL); /* * As of the timer_settime(), we will receive our pulse * in 1.5 seconds (the itime.it_value) and every 1.5 * seconds thereafter (the itime.it_interval) */ for (;;) { rcvid = MsgReceive(chid, &msg, sizeof(msg), NULL); if (rcvid == 0) {/* we got a pulse */ if (msg.pulse.code == MY_PULSE_CODE) { printf("we got a pulse from our timer"); }/* else other pulses ... */ }/* else other messages ... */ } }