powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Unix-системы [игнор отключен] [закрыт для гостей] / семафоры, процессы, etc, разделяемая память
7 сообщений из 7, страница 1 из 1
семафоры, процессы, etc, разделяемая память
    #36614273
24spam@tut.by
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте!
Честно признаюсь - близится сессия, поэтому необходима помощь компетентных специалистов.

Стоит следующая задача

Cоздать два дочерних процесса. Родительский процесс создаёт семафор (сем1) и разделяемую память. Оба дочерних процесса непрерывно записывают в разделяемую память по 100 строк вида: номер_строки pid_процесса текущее_время (мсек). Всего процессы должны записать 1000 строк. Семафор сем1 используется процессами для разрешения кому из процессов получить доступ к разделяемой памяти. Родительский процесс читает из файла по 75 строк и выводит их на экран. Дочерние процессы начинают операции с файлом после получения сигнала SIGUSR1 от родительского процесса.


Вот мой код

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
#include <linux/sem.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <signal.h>

int start =  0 ;

#define LEN  20 

pid_t chpid [ 2 ];

int main (int argc, char *argv [])
{
    struct timeval c_time;
    void c_action (int);
    static struct sigaction pact, cact;
    char str [LEN];
    id_t pid;


     shm_unlink("myshered.shm");

     int fd_shm;
      
     if((fd_shm = shm_open("myshered.shm", O_RDWR|O_CREAT,  0777 )) <  0 )
     {perror ("error create shm");   return( 1 );}


    // создаем семафор
    int j,n,i= 0 ;


    int semid = semget(IPC_PRIVATE,  4 ,  0666  | IPC_CREAT );
    if (semid <  0 ){
        perror("semget");
            return  1 ;}

    struct sembuf s_red[ 2 ] = { 0 , - 1 , IPC_NOWAIT,  1 ,  1 , IPC_NOWAIT};
    struct sembuf s_green[ 2 ] = { 0 ,  1 , IPC_NOWAIT,  1 , - 1 , IPC_NOWAIT}; 
    struct sembuf s_wait[ 2 ] = { 0 ,  0 ,  0 ,  1 ,  0 ,  0 }; 
    struct sembuf s_readed = { 2 ,  0 ,  0 }; 
    struct sembuf s_lock = { 2 ,  1 , IPC_NOWAIT}; 
    struct sembuf s_unlock = { 2 , - 1 , IPC_NOWAIT}; 

    union semun arg;

    arg.val =  0 ;
    semctl(semid,  0 , SETVAL, arg);
    arg.val =  1 ;
    semctl(semid,  1 , SETVAL, arg);
    arg.val =  0 ;
    semctl(semid,  2 , SETVAL, arg);


    // создаем два процесса
    for (j= 0 ; j< 2 ; j++) {
    switch (chpid [j] = fork ()) {
    case - 1 :
        printf ("Fork call error\n");
        return  1 ;
    case  0 :
        //child
        cact.sa_flags = SA_SIGINFO;
        cact.sa_sigaction = (void *) c_action;
            sigaction (SIGUSR1, &cact, NULL);
        printf("child #%d\n",getpid());
        while (i <=  1000 ) {
          // ожидаем разрешения
           
            if ((start)&&
            (semop( semid, &s_readed,  1 )== 0 )&&
            (semop( semid, &s_wait[j],  1 )== 0 ))
            { 
            lseek (fd_shm,  0 , SEEK_END);
            i = semctl(semid,  3 , GETVAL);
            if (i== 1000 )break;
            for (n= 0 ;n< 100 ;n++){            
                gettimeofday(&c_time,NULL);
                sprintf (str,"%4d #%5d :%6d\n", i+n+ 1 , 
                    getpid (), c_time.tv_usec);
                write(fd_shm,str,LEN);
            }
            i+=n;
                arg.val = i;
                semctl(semid,  3 , SETVAL, arg);
            // переключаем поток
            if (j== 0 ) semop( semid, &s_green,  2 );
            else semop( semid, &s_red,  2 );  

            }
        }       
        return  0 ;
    }
    }
    printf("father #%d\n",getpid());
    //father
    kill (chpid [ 0 ], SIGUSR1);
    kill (chpid [ 1 ], SIGUSR1);
    i= 0 ;
        while (i <  1000 ) {
            sleep( 1 );
            // ожидаем разрешения
            j=semctl(semid,  3 , GETVAL);
            if( (j>i+ 75 )||(j== 1000 ))
            {
            // блокируем
                semop( semid, &s_lock,  1 );      
            // читаем   
            lseek (fd_shm, i*LEN, SEEK_SET);

            for (n= 0 ;n< 75 ;n++){
                if (i+n == 1000 ) break;
                read(fd_shm,str,LEN);
                printf ("%s", str);         
            }
                i+=n; 
            // разблокируем 
                semop( semid, &s_unlock,  1 );
            }           
        }
    /*close(fd);*/

    shm_unlink("myshered.shm");
    semctl(semid,  0 , IPC_RMID);
    return  0 ;
}

void c_action (int sig)
    {
      start =  1 ;
      printf("action #%d\n",getpid());
    }


Проблема в том, что на экран выводится только 1-ые 75 строк. Как организовать вывод остальных? Подозреваю, что затык где-то в том месте, где должно происходить считывание следующих 75 строк. Это или
Код: plaintext
1.
 lseek (fd_shm, i*LEN, SEEK_SET);
или
Код: plaintext
1.
read(fd_shm,str,LEN);

Как это исправить?
...
Рейтинг: 0 / 0
семафоры, процессы, etc, разделяемая память
    #36614372
avb1003
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
24spam@tut.by,
Странно, что у Вас она вообще скомпилировалась.
У меня скомпилировалась после изменений:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
rcsdiff -r1. 1  tshm.c
1c1
< #include <linux/sem.h>
---
> // #include <linux/sem.h>
2a3
> #include <sys/sem.h>
17a19, 25 
>    union semun
>    {
>      int val;                         //  value for SETVAL
>      struct semid_ds *buf;            // buffer for IPC_STAT & IPC_SET
>      unsigned short int *array;               // array for GETALL & SETALL
>      struct seminfo *__buf;           //  buffer for IPC_INFO
>    };
и после этого все заработало - программа выдала все 1000 строк. Правда компиляция при этом выдавала
предупреждения, так как вместо
Код: plaintext
1.
2.
            if (j== 0 ) semop( semid, &s_green,  2 );
            else semop( semid, &s_red,  2 );  
правильно писать
Код: plaintext
1.
2.
            if (j== 0 ) semop( semid, s_green,  2 );
            else semop( semid, s_red,  2 );  
...
Рейтинг: 0 / 0
семафоры, процессы, etc, разделяемая память
    #36614685
24spam@tut.by
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Большое спасибо за помощь. Я только не совсем понял на счёт

rcsdiff -r1.1 tshm.c
1c1
< #include <linux/sem.h>
---
> // #include <linux/sem.h>
2a3
> #include <sys/sem.h>
17a19,25
> union semun
> {
> int val; // value for SETVAL
> struct semid_ds *buf; // buffer for IPC_STAT & IPC_SET
> unsigned short int *array; // array for GETALL & SETALL
> struct seminfo *__buf; // buffer for IPC_INFO
> };

Это нужно вставить вместо union semun arg; ?
...
Рейтинг: 0 / 0
семафоры, процессы, etc, разделяемая память
    #36615648
avb1003
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
24spam@tut.by,
24spam@tut.by
Большое спасибо за помощь. Я только не совсем понял на счёт

rcsdiff -r1.1 tshm.c
...Это означает, что программа была сохранена под именем tshm.c и сразу передана под управление RCS.
Команда rcsdiff показывает разницу между текущем состоянием файла и указанной версией в RCS-файле.
Читайте man rcs ci rcsdiff.
Код: plaintext
1.
2.
3.
4.
1c1
< #include <linux/sem.h>
---
> // #include <linux/sem.h>
- этот тот фрагмент означает, что строка с номером 1 в исходном файле "#include <linux/sem.h>" заменена
строкой "// #include <linux/sem.h>" в текущем.
Код: plaintext
1.
2a3
> #include <sys/sem.h>
- этот фрагмент означает, что в текущем файле после строки с номером 2 в исходном файле добавлена строка "#include <sys/sem.h>". Оставшийся фрагмент означает, что после строки
с номером 17 в исходном файле добавлено определение union-а semun. То есть, иными словами, вместо "linux/sem.h" нужно включать ""sys/sem.h". так как это написано в man-е по semop, semctl и т.д, и нужно определять самостоятельно union semun так, как это написано вman semctl
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
...
 The calling program  must define  this union as follows:

           union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           };
...
или(sys/sem.h включает bits/sem.h) в/usr/include/bits.h
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
...
/* The user  should define a union  like the following to use it for arguments
   for `semctl'.

   union semun
   {
     int val;                           <= value for SETVAL
     struct semid_ds *buf;              <= buffer for IPC_STAT & IPC_SET
     unsigned short int *array;         <= array for GETALL & SETALL
     struct seminfo *__buf;             <= buffer for IPC_INFO
   };

   Previous versions of this file used to define this union but this is
   incorrect.  One can test the macro _SEM_SEMUN_UNDEFINED to see whether
   one must define the union or not.  */
...
...
Рейтинг: 0 / 0
семафоры, процессы, etc, разделяемая память
    #36615689
24spam@tut.by
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Большое спасибо. Буду пробовать.
...
Рейтинг: 0 / 0
семафоры, процессы, etc, разделяемая память
    #36616376
24spam@tut.by
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 avb1003

ОГРОМНОЕ СПАСИБО!!!
...
Рейтинг: 0 / 0
семафоры, процессы, etc, разделяемая память
    #36617133
24spam@tut.by
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вот ещё такой вопос.
Как сделать так, чтобы родительский процесс посылал сигнал SIGUSR1 одновременно 2 процессам сразу?

Т.е., чем нужно заменить строки ?
Код: plaintext
1.
2.
    kill (chpid [ 0 ], SIGUSR1);
    kill (chpid [ 1 ], SIGUSR1);
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Unix-системы [игнор отключен] [закрыт для гостей] / семафоры, процессы, etc, разделяемая память
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]