Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > Сообщения между процессами


Автор: 5pY 24.5.2011, 02:13
В программе идёт обмен сообщениями между процессом-предком и двумя дочерними. Почему-то сообщения от второго дочернего процесса повторяются, хотя код такой же как и в первом(только типы сообщений разные естественно). Обработка сообщений предком тоже одинакова.
Вот коды:
Код

Предок:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#define pr1_END 11
#define pr1_STOP 22
#define pr1_RUN 33
#define pr2_END 44
#define pr2_STOP 55
#define pr2_RUN 66
int main(int argc,char **argv)
{
    pid_t a;
    pid_t b;
    pid_t pid2,pid1; 
    int status,ret,pr1=0,pr2=0;
    int msqid; /* IPC дескриптор для очереди сообщений */
    bool pr1_exit=false,pr2_exit=false;
    char pathname[] = "lab6.c"; /* Имя файла, использующееся для генерации ключа. Файл с таким именем должен существовать в текущей директории */
     key_t key; /* IPC ключ */ 
     int i,len,maxlen; /* Счетчик цикла и длина информативной части сообщения */
     /* Ниже следует пользовательская структура для сообщения */
     struct newmsgbuf
    {
        long mtype;
        int mtext[1];
    }buf;
     /* Генерируем IPC ключ из имени файла lab6.c в текущей директории и номера экземпляра очереди сообщений 0. */
printf("start!");     
if((key = ftok(pathname,13)) < 0){
         printf("Ошибка! Ключ не сгенерирован!");
         exit(-1);
     }
     /* Пытаемся получить доступ по ключу к очереди сообщений,если она существует, или создать ее, с правами доступа read & write для всех пользователей */ 
     
    msqid = msgget(key, 0666 | IPC_CREAT);
        a = fork();
    b = fork();
    if(a==0)
    {
        ret=execl("./nasl1.out","nasl1",NULL);
    }
    if(b==0)
    {
        ret=execl("./nasl2.out","nasl2",NULL);
    }

        while(1)
        { 
             maxlen = 128;
            if(pr2_exit==false)
            {
            len = msgrcv(msqid,&buf, maxlen, pr2_STOP, 0);
             if (buf.mtype == pr2_STOP)
                {
                buf.mtype = pr2_RUN;
                len = 0;
                 msgsnd(msqid, &buf,len, 0);
                len = msgrcv(msqid,&buf, maxlen, 2, 0);
                if (buf.mtype == 2){
                    printf("сообщение №%d от процесса №%ld\n",buf.mtext[0],buf.mtype);
                    pr2=pr2+1;
                 }
                if(pr2==15)len = msgrcv(msqid,&buf, maxlen, pr2_END, 0);
                 if (buf.mtype == pr2_END){
                    pr2_exit=true;
                     }
                }
             }
            sleep(1);
            if(pr1_exit==false)
            {
            
            len = msgrcv(msqid,&buf, maxlen, pr1_STOP, 0);
             if (buf.mtype == pr1_STOP)
                {
                buf.mtype = pr1_RUN;
                len = 0;
                 msgsnd(msqid, &buf,len, 0);
                len = msgrcv(msqid,&buf, maxlen, 1, 0);
                if (buf.mtype == 1){
                    printf("сообщение №%d от процесса №%ld\n",buf.mtext[0],buf.mtype);
                    pr1=pr1+1;
                 }
                if(pr1==15)len = msgrcv(msqid,&buf, maxlen, pr1_END, 0);
                 if (buf.mtype == pr1_END){
                    pr1_exit=true;
                     }
                }
             }
        sleep(1);
        
            if (pr1_exit==true && pr2_exit==true){
            msgctl(msqid, IPC_RMID, NULL);
             exit(0);
         }
    }
}
    


Дочерний 1(его сообщения дублируются):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <time.h>

#define pr1_END 11
#define pr1_STOP 22
#define pr1_RUN 33

int main()
{
    
    int msqid; /* IPC дескриптор для очереди сообщений */
char pathname[] = "lab6.c"; /* Имя файла, использующееся для генерации ключа. Файл с таким именем должен существовать в текущей директории */
    key_t key; /* IPC ключ */ 
    int i,len,maxlen; /* Счетчик цикла и длина информативной части сообщения */
    /* Ниже следует пользовательская структура для сообщения */
    struct newmsgbuf
    { 
        long mtype;
        int mtext[1]; 
    } buf;
    /* Генерируем IPC ключ из имени файла lab6.c в текущей директории и номера экземпляра очереди сообщений 0. */
    if((key = ftok(pathname,13)) < 0){
        printf("Наследник 1, ошибка генерации ключа!");
        exit(-1);
    }
    /* Пытаемся получить доступ по ключу к очереди сообщений,если она существует, или создать ее, с правами доступа read & write для всех пользователей */ 
    msqid = msgget(key, 0666 | IPC_CREAT);
    /* Посылаем в цикле 100 сообщений с типом 1 в очередь сообщений, идентифицируемую msqid.*/
    for (i = 1; i <= 15; i++){
    buf.mtype = pr1_STOP;
     len = 0;
     msgsnd(msqid,&buf,len, 0);
    maxlen = 128;
        len = msgrcv(msqid, &buf, maxlen, pr1_RUN, 0);
        if (buf.mtype == pr1_RUN){
        buf.mtype = 1;
        buf.mtext[0]=i;
         msgsnd(msqid, &buf,sizeof(buf.mtext), 0);
         }
       
    }
    /* Отсылаем сообщение, которое заставит получающий процесс
    прекратить работу, с типом D1_END и длиной 0 */ 
    buf.mtype = pr1_END;
    len = 0;
    msgsnd(msqid,&buf,len, 0);
    exit(0);
}


Дочерний 2(работает как положено):


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <time.h>

#define pr2_END 44
#define pr2_STOP 55
#define pr2_RUN 66

int main()
{
    
    int msqid; /* IPC дескриптор для очереди сообщений */
char pathname[] = "lab6.c"; /* Имя файла, использующееся для генерации ключа. Файл с таким именем должен существовать в текущей директории */
    key_t key; /* IPC ключ */ 
    int i,len,maxlen; /* Счетчик цикла и длина информативной части сообщения */
    /* Ниже следует пользовательская структура для сообщения */
    struct newmsgbuf
    { 
        long mtype;
        int mtext[1]; 
    } buf;
    /* Генерируем IPC ключ из имени файла lab6.c в текущей директории и номера экземпляра очереди сообщений 0. */
    if((key = ftok(pathname,13)) < 0){
        printf("Наследник 2, ошибка генерации ключа!");
        exit(-1);
    }
    /* Пытаемся получить доступ по ключу к очереди сообщений,если она существует, или создать ее, с правами доступа read & write для всех пользователей */ 
    msqid = msgget(key, 0666 | IPC_CREAT);
    /* Посылаем в цикле 100 сообщений с типом 1 в очередь сообщений, идентифицируемую msqid.*/
    for (i = 1; i <= 15; i++){
    buf.mtype = pr2_STOP;
     len = 0;
     msgsnd(msqid,&buf,len, 0);
    maxlen = 128;
        len = msgrcv(msqid, &buf, maxlen, pr2_RUN, 0);
        if (buf.mtype == pr2_RUN){
        buf.mtype = 2;
        buf.mtext[0]=i;
         msgsnd(msqid, &buf,sizeof(buf.mtext), 0);
         }
        
    }
    /* Отсылаем сообщение, которое заставит получающий процесс
    прекратить работу, с типом D1_END и длиной 0 */ 
    buf.mtype = pr2_END;
    len = 0;
    msgsnd(msqid,&buf,len, 0);
    exit(0);
}




Автор: svlary 24.5.2011, 05:29
Вот эта конструкция ошибочна :

Код

    a = fork();
    b = fork();


На самом деле она означает вот что :
  • Родительский процесс порождает дочерний
  • Потом И родительский И дочерний ОБА порождают еще по одному процессу.

Т.е., в итоге, у Вас получается не три, а четыре процесса smile

Автор: 5pY 24.5.2011, 21:27
А если сделать так:
Код

a=fork();
if (a>0) b=fork;


будет работать? Просто нет возможности проверить

Автор: MAKCim 24.5.2011, 21:32
5pY, 
проще сесть, почитать мануал и разобраться
на полном серьезе

Автор: svlary 25.5.2011, 05:04
Цитата(MAKCim @  24.5.2011,  21:32 Найти цитируемый пост)
почитать мануал и разобраться

  Вот здесь :
http://www.intuit.ru/department/se/pposix/class/free/7/
очень хорошо и подробно все описано.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)