[<<Previous Entry]
[^^Up^^]
[Next Entry>>]
[Menu]
[About The Guide]
Решения
sendone.c:
1 /* sender */
2 #include <string.h>
3 #include <unistd.h>
4 #include <sys/types.h>
5 #include <sys/ipc.h>
6 #include <sys/msg.h>
7 static struct mymsg {
8 long t;
9 char a[60];
10 } x = { 1L,"Hello" };
11
12 /* sender must run first
13 either by placing sender in background
14 or running it at one terminal
15
16 receiver runs either in foreground
17 or at a second terminal
18 */
19
20 main()
21 {
22 int mid;
23
24 /*for a key, have student use numeric part of login id*
25 mid = msgget(getuid(),IPC_CREAT | 0666);
26
27 /* creation of the queue could have been done earlier,
28 and if so, only need:
29 mid = msgget(11L, 0);
30 */
31
32 msgsnd(mid,&x,strlen(x.a) + 1,0);
33
34 sleep(60); /* delay to ensure receipt */
35 msgctl(mid,IPC_RMID,NULL);
36
37 /* alternative to sleep and IPC_RMID: ipcrm -q qid */
38 }
recvone.c:
1 /* receiver */
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <sys/types.h>
5 #include <sys/ipc.h>
6 #include <sys/msg.h>
7
8
9 main()
10 {
11 struct msgbuf {
12 long t;
13 char a[60];
14 } x;
15 int mid, rtn;
16
17 mid = msgget(getuid(),0);
18 rtn=msgrcv(mid,&x,60,0L,0);
19 printf("rtn=%d type=%ld text=%s\n", rtn, x.t, x.a);
20 }
ВЫЗОВ:
$ sendone&
2894
$ recvone
received=Hello
Рассылка одного сообщения многим процессам
msg_wall_s.c:
1 /* Sender:
2 Text entered at stdin is sent as message to
3 several (child) processes.
4 Repeated until stdin EOF.
5 Exits after each receiver has sent back
6 a completion notification message.
7 */
8 #include <sys/types.h>
9 #include <unistd.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <sys/ipc.h>
13 #include <sys/msg.h>
14 #include <string.h>
15 #define MAX_SZ 80
16 #define NCHILD 3
17 #define WAIT_SOLE_USE(MSGQID) { \
18 int still_active = NCHILD; \
19 int i; \
20 pid_t s_pid; \
21 s_pid = getpid(); \
22 while(still_active){ for(i=0;i<NCHILD;i++)\
23 if(msgrcv(MSGQID,&buf,MAX_SZ,s_pid,IPC_NOWAIT)!=-
24 if(!strncmp(buf.mtext,"DONE",4)) still_active--;\
25 sleep(2); \
26 } \
27 }
28 main()
29 {
30 int msgqid;
31 struct {
32 long mtype;
33 char mtext[MAX_SZ];
34 } buf;
35 int msg_length;
36 static char qid_evar[40];
37 static char *envp[2] = { qid_evar };
38 pid_t this_fork;
39 int child;
40 pid_t r_pid[NCHILD];
41 char child_name[20];
42 int eof = 0;
43
44
45 if((msgqid = msgget(IPC_PRIVATE, IPC_CREAT | 0660)) == -1)
46 { perror("Sender can't make msg queue");
47 exit(1);
48 }
49
50 sprintf(qid_evar, "MQID=%d", msgqid);
51
52 for(child=0; child < NCHILD; child++){
53 this_fork = fork();
54 if(this_fork == -1){
55 perror("fork failed");
56 exit(2);
57 }
58 else if(this_fork == 0){
59 sprintf(child_name, "mwall_r%d", child);
60 execle("msg_wall_r",child_name,0,envp);
61 perror("exec failed");
62 exit(3);
63 }
64 else r_pid[child] = this_fork;
65 }
66
67 setbuf(stdout, NULL);
68 while(1){
69 fprintf(stdout,
70 "Enter message to be sent to all receivers: ");
71 if(gets(buf.mtext) == NULL){
72 fprintf(stdout,"\n");
73 eof++;
74 strcpy(buf.mtext,"EOF");
75 }
76 msg_length = strlen(buf.mtext) + 1;
77 for(child=0; child < NCHILD; child++){
78 buf.mtype = r_pid[child];
79 if(msgsnd(msgqid, &buf, msg_length, 0) == -1) {
80 perror(" Producer msgsnd error");
81 exit(4);
82 }
83
84 }
85
86 if(eof) break;
87
88 sleep(1);
89 }
90
91
92 WAIT_SOLE_USE(msgqid);
93
94 msgctl(msgqid, IPC_RMID, NULL);
95 return(0);
96 }
msg_wall_r.c:
1 /* Receiver:
2 Loops receiving messages from a sender.
3 Received messages are printed on stdout.
4 After receiving EOF message, receiver exits.
5 */
6 #include <sys/types.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <stdio.h>
10 #include <sys/ipc.h>
11 #include <sys/msg.h>
12 #include <string.h>
13 #define MAX_SZ 80
14
15 main(int argc, char *argv[])
16 {
17 pid_t pid;
18 char *valuep;
19 int msgqid;
20 struct {
21 long mtype;
22 char mtext[MAX_SZ];
23 } buf;
24
25 pid = getpid();
26
27 if((valuep = getenv("MQID")) == NULL){
28 fprintf(stderr,"%s: can't getenv MQID\n", argv[0]);
29 exit(1);
30 }
31 else sscanf(valuep, "%d", &msgqid);
32
33 while(1){
34 msgrcv(msgqid,&buf,MAX_SZ,pid,MSG_NOERROR);
35 printf("%s received '%s'\n",argv[0],buf.mtext);
36 if(!strcmp(buf.mtext,"EOF")) break;
37 }
38
39 buf.mtype = getppid();
40 strcpy(buf.mtext,"DONE");
41 if(msgsnd(msgqid, &buf, strlen(buf.mtext), 0) == -1) {
42 fprintf(stderr,"%s: msgsnd error\n", argv[0]);
43 exit(2);
44 }
47 return(0);
48 }
ВЫЗОВ:
$ msg_wall_s
Enter message to be sent to all receivers: abcde
mwall_r0 received 'abcde'
mwall_r1 received 'abcde'
mwall_r2 received 'abcde'
Enter message to be sent to all receivers: xyz
mwall_r0 received 'xyz'
mwall_r1 received 'xyz'
mwall_r2 received 'xyz'
Enter message to be sent to all receivers: <CTRL D>
mwall_r0 received 'EOF'
mwall_r1 received 'EOF'
mwall_r2 received 'EOF'
$
Несколько процессов, сообщающих состояние процессу-мастеру
msg_rpt_m.c:
1 /* Master:
2 Receives status messages from several processes.
3 Terminates after receiving completion
4 message from each.*/
5 #include <sys/types.h>
6 #include <unistd.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <sys/ipc.h>
10 #include <sys/msg.h>
11 #include <string.h>
12 #define MAX_SZ 80
13 #define NCHILD 3
14 #define MSG_RCV(FROM_CH) { \
15 if(msgrcv(msgqid,&buf,MAX_SZ,FROM_CH, IPC_NOWAIT)!=-1){ \
16 if(!strncmp(buf.mtext,"DONE",4)){ \
17 still_active--; \
18 r_pid[child] = INACTIVE; \
19 } \
20 printf("From %ld:%s\n",buf.mtype,buf.mtext);\
21 } \
22 }
23
24 #define INACTIVE 0
25
26 main()
27 {
28 int msgqid;
29 struct {
30 long mtype;
31 char mtext[MAX_SZ];
32 } buf;
33 static char qid_evar[40];
34 static char *envp[2] = { qid_evar };
35 pid_t this_fork;
36 int child;
37 pid_t r_pid[NCHILD];
38 char child_name[20];
39 int still_active = NCHILD;
40
41
42 if((msgqid=msgget(IPC_PRIVATE,IPC_CREAT|0660))==-1) {
43 perror("Master can't make msg queue");
44 exit(1);
45 }
46
47 sprintf(qid_evar, "MQID=%d", msgqid);
48
49 for(child=0; child < NCHILD; child++){
50 this_fork = fork();
51 if(this_fork == -1){
52 perror("fork failed");
53 exit(2);
54 }
55 else if(this_fork == 0){
56 sprintf(child_name, "msg_rpt_s%d",child);
57 execle("msg_rpt_s", child_name, 0,envp);
58 perror("exec failed");
59 exit(3);
60 }
61 else r_pid[child] = this_fork;
62 }
63
64 still_active = NCHILD;
65
66 while(1){
67 for(child=0;still_active&&child<NCHILD;child++){
68 if(r_pid[child]) MSG_RCV(r_pid[child]);
69 sleep(2);
70
71 }
72
73 if(still_active == 0) break;
74
75 }
76
77
78 msgctl(msgqid, IPC_RMID, NULL);
79 return(0);
80 }
msg_rpt_s.c:
1 /* Sender:
2 Several copies of this programm will send status
3 reports to (parent) master every second.
4 Each sends a random number of messages 1 - 10.
5 It sends a completion message just before exiting.
6 */
7 #include <sys/types.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <sys/ipc.h>
12 #include <sys/msg.h>
13 #include <string.h>
14 #define MAX_SZ 30
15
16 main(int argc, char *argv[])
17 {
18 pid_t pid;
19 char *valuep;
20 int mqid;
21 struct {
22 long mtype;
23 char mtext[MAX_SZ];
24 } buf;
25 int i, ub;
26
27
28 if((valuep = getenv("MQID")) == NULL){
29 fprintf(stderr,"%s: can't getenv MQID\n",argv[0]);
30 exit(1);
31 }
32 else sscanf(valuep, "%d", &mqid);
33
34
35 pid = getpid();
36
37 srand( (unsigned)pid );
38 ub = rand() % 10 + 2;
39
40 buf.mtype = pid;
41
42 for(i=1; i <= ub; i++){
43 if(i==ub) strcpy(buf.mtext,"DONE");
44 else sprintf(buf.mtext,"status mesg #%d", i);
45 if(msgsnd(mqid,&buf,strlen(buf.mtext)+1,0)==-1) {
46 fprintf(stderr,"%s: msgsnd error\n", argv[0]);
47 exit(2);
48 }
49 sleep(1);
50 }
51
52 exit(0);
53 }
ВЫЗОВ:
$ msg_rpt_m
From 14437: status mesg #1
From 14438: status mesg #1
From 14439: status mesg #1
From 14437: status mesg #2
From 14438: status mesg #2
From 14439: status mesg #2
From 14437: status mesg #3
From 14438: status mesg #3
From 14439: status mesg #3
From 14437: status mesg #4
From 14438: status mesg #4
From 14439: status mesg #4
From 14437: status mesg #5
From 14438: status mesg #5
From 14439: DONE
From 14437: DONE
From 14438: status mesg #6
From 14438: DONE
$