[<<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
$