LINUX.ORG.RU

Семафоры


0

0

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/stat.h>

int semWait(int sem,int n)

{

struct sembuf sem_op;

sem_op.sem_num = 0;

sem_op.sem_op = n;

sem_op.sem_flg = 0;

return semop(sem,&sem_op,1);

}

int main(int argc, char **argv)

{

pid_t pid;

int sem_id;

key_t key;

int fd;

/* Создаем новый семафор */

if((sem_id =

semget(IPC_PRIVATE,1,IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR)) == -1)

perror("Can't creat semafor"),exit(1);

if((pid = fork()) == 0)

{

while(1)

{

printf("Потомок\n");

}

} else {

while(2)

{

printf("Родитель\n");

}

}

if((semctl(sem_id,1,IPC_RMID)) == -1)

perror("semctl");

exit(0);

}

Помогите синхронизировать родителя(родитель выпо-ся первым) с сыном, нужно это сделать с помощью семафоров. Семафоры начал только изучать. Зарание спасибо!

anonymous

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

int semWait(int sem,int n)
{
   struct sembuf sem_op;
   sem_op.sem_num = 0;
   sem_op.sem_op = n;
   sem_op.sem_flg = 0;
return semop(sem,&sem_op,1);
}

int main(int argc, char **argv)
{

   pid_t pid;
   int sem_id;
   key_t key;
   int fd;

/* Создаем новый семафор */

if((sem_id =
semget(IPC_PRIVATE,1,IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR)) == -1)
    perror("Can't creat semafor"),exit(1);

if((pid = fork()) == 0)
{
    while(1)
    {
        printf("Потомок\n");
    }

} else {

    while(2)
    {
        printf("Родитель\n");

    }

}

if((semctl(sem_id,1,IPC_RMID)) == -1)
perror("semctl");
exit(0);
} 

anonymous
()
Ответ на: комментарий от Chumka

мне нужно чтобы выполнялся 2-ой цикл потом 1-ый, и так поочереди. т.е. во 2 цикле заблокировать потомка при помощи semop(), подождать когда цикл выполнится, и отблокировать потомка а родителя заблокировать для того чтобы подождать потомка ...

anonymous
()
Ответ на: комментарий от anonymous

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

int semWait(int sem,int n)
{
   struct sembuf sem_op;
   sem_op.sem_num = 0;
   sem_op.sem_op = n;
   sem_op.sem_flg = 0;
return semop(sem,&sem_op,1);
}

inline void lock_semaphore ( const int sem_id);
inline void unlock_semaphore ( const int sem_id);

union senum
{
	int val;
	struct semid_df *buf;
	unsigned short int *array;
	struct seminfo *__buf;
};



struct sembuf operations_with_semaphore[1];

int main(int argc, char **argv)
{

   pid_t pid;
   int sem_id;
   key_t key;
   int fd;

/* Создаем новый семафор */

if((sem_id =
semget(IPC_PRIVATE,1,IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR)) == -1)
    perror("Can't creat semafor"),exit(1);

union senum argument_for_semctl;
short int array_for_semctl[1];
array_for_semctl[0] = 1;
argument_for_semctl.array = array_for_semctl;

if ( semctl( sem_id, 
			0, SETALL, argument_for_semctl) == -1)
	perror ( "semctl error:");


if((pid = fork()) == 0)
{
    sleep ( 1);
    while(1)
    {
	lock_semaphore ( sem_id);
        printf("Потомок\n");
	unlock_semaphore ( sem_id);
    }

} else {

    while(2)
    {
	lock_semaphore ( sem_id);
        printf("Родитель\n");
	unlock_semaphore ( sem_id);

    }

}

//if((semctl(sem_id,1,IPC_RMID)) == -1)
//perror("semctl");
exit(0);
} 

//fuction for lock semaphore
inline void lock_semaphore ( const int sem_id)
{
	operations_with_semaphore[0].sem_num = 0;
	operations_with_semaphore[0].sem_op = -1;
	operations_with_semaphore[0].sem_flg = SEM_UNDO;
	semop ( sem_id, operations_with_semaphore, 1);
//lock semaphore
};
//------------------------------------------------------------------------------
-
//fuction for unlock semaphore
inline void unlock_semaphore ( const int sem_id)
{
	operations_with_semaphore[0].sem_num = 0;
	operations_with_semaphore[0].sem_op = 1;
	operations_with_semaphore[0].sem_flg = SEM_UNDO;
	semop ( sem_id, operations_with_semaphore, 1);
//unlock semaphore
};

anonymous
()
Ответ на: комментарий от anonymous

Появился еще один вопросец. А без sleep(1) можно как нибудь обойтись? Просто не прикольно ждать 1 сек. Зарание спасибо.

anonymous
()
Ответ на: комментарий от stalcker

По поводу флага SEM_UNDO, если он установлен тогда после удачного вызова semop(), семафор устанавливается в начальное значение и ресурс отблокируется, я правильно понимаю значение этого флага?

anonymous
()
Ответ на: комментарий от stalcker

Помоему проще сделать waitpid в родителе.. Тогда дочка тоже выполнится первой, а родитель будет ее ждать )

OxiD ★★★★
()
Ответ на: комментарий от stalcker

Мне не совсем понятен этот кусок кода:

sleep(1);
while(1)
    {
	lock_semaphore ( sem_id);
        printf("Потомок\n");
	unlock_semaphore ( sem_id);
    }

} else {

    while(2)
    {
	lock_semaphore ( sem_id);
        printf("Родитель\n");
	unlock_semaphore ( sem_id);

    }

Значит первым выполняется родитель, функция lock_semaphore(sem_id)
блокирует этот процесс(родителя), потом(как я понимаю) потомок блокирует себя и в итоге 2 процесса заблокированы? Просто пока нет возможност&#1110; провер&#1110;ть этот код. Прокоментируйте пожалуйста этот участок кода. Зарание огромное спасибо.

anonymous
()
Ответ на: комментарий от OxiD

Мне нужно это реализовать именно с помощью семафоров.

anonymous
()
Ответ на: комментарий от anonymous

>Помоему проще сделать waitpid в родителе.. Тогда дочка тоже выполнится первой, а родитель будет ее ждать )

Можно и так но, как я понял, ему надо что бы чередовался доступ к ресурсам.

>Значит первым выполняется родитель, функция lock_semaphore(sem_id) блокирует этот процесс(родителя),
потом(как я понимаю) потомок блокирует себя и в итоге 2 процесса заблокированы? Просто пока нет
возможност&#1110; провер&#1110;ть этот код. Прокоментируйте пожалуйста этот участок кода. Зарание
огромное спасибо.

Потомок сразу после "родов" засыпает на 1 сек. в это время начинает свою работу родитель.

Родитель(один процесс) блокирует семафор и печатает, раблокирует семафор, опять блокирует,
опять печатает, опять раблокирует тут захватить семафор пытается другой процесс(потомок)
если семафор заблокирован то этот второй процесс засыпает до тех пор пока семафор не
освободится затем просыпается и работает с ресурсом а первый(ну, или сколко их там к тебя)
ожидеат пока семафор освободится.

stalcker
()
Ответ на: комментарий от stalcker

В том то и проблема что мне нужна поочередность выполнения(Родитель Сын
Родитель Сын и т.д.), а в приведенном выше коде поочередность не реализуется.

anonymous
()
Ответ на: комментарий от anonymous

Что значит не реализуется? У тебя наверное однопроцессорная машина? Тогда конечно ты ничего не увидишь один процесс отработал свой квант потом второй т.е. многопроцессорности нет и реально в конкретный момент времени выполняется только один процесс. А для поочередности можно в расшаренной памяти писать номер процесса т.е. первый ждет пока там не появится цифра 2(второй отработал) и наоборот. Еще проще если использовать каналы. Ты опиши задачу точнее, это задание в институте?

stalcker
()
Ответ на: комментарий от stalcker

1) Машина однопроцессорная.
2) Задача типа производитель потребитель, т.е. один процесс(родитель)
   пишет в файл символы введеные с клавиатуры(потомок ожидает в 
   это время) а второй процесс(потомок) читает           
   эти данные из файла и выводит их на экран.
И все это мне нужно реализовать либо с помощью семафоров либо шареной 
памятью.

anonymous
()
Ответ на: комментарий от anonymous

Используй каналы, а так я описал что делать, создаешь семафор расшареваешь память и семафором регулируешь к ней доступ.

stalcker
()
Ответ на: комментарий от stalcker

А примерчик можно набросать с использованием шариной памяти? Я просто
до shared memory еще не дошол, а завтра нужно это все здать. Если 
вам это сложно(лень etc), тогда и наэтом огромное спасибо)).

anonymous
()
Ответ на: комментарий от anonymous

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

int semWait(int sem,int n)
{
   struct sembuf sem_op;
   sem_op.sem_num = 0;
   sem_op.sem_op = n;
   sem_op.sem_flg = 0;
return semop(sem,&sem_op,1);
}

inline void lock_semaphore ( const int sem_id);
inline void unlock_semaphore ( const int sem_id);

int seg_mem_id;
char *shared_mem;

union senum
{
int val;
struct semid_df *buf;
unsigned short int *array;
struct seminfo *__buf;
};

struct sembuf operations_with_semaphore[1];

int main(int argc, char **argv)
{

   pid_t pid;
   int sem_id;
   key_t key;
   int fd;

/* Создаем новый семафор */

if((sem_id =
semget(IPC_PRIVATE,1,IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR)) == -1)
    perror("Can't creat semafor"),exit(1);

union senum argument_for_semctl;
short int array_for_semctl[1];
array_for_semctl[0] = 1;
argument_for_semctl.array = array_for_semctl;

if ( semctl( sem_id, 
0, SETALL, argument_for_semctl) == -1)
perror ( "semctl error:");


//creaete shared memory
if ( (seg_mem_id = shmget ( IPC_PRIVATE, 1024, 
				IPC_CREAT | IPC_EXCL | 0600)) == -1)
	perror ( "shmget error:");
shared_mem = (char *) shmat ( seg_mem_id, (void*) 0, 0);
(*(int*)shared_mem) = 0;

int i = 0;

if((pid = fork()) == 0)
{
    sleep ( 1);
    while(1)
    {
		lock_semaphore ( sem_id);
		if ( i < (*(int*)shared_mem))
		{
			i = (*(int*)shared_mem);
			printf("Потомок, %d\n", i);
		};
		unlock_semaphore ( sem_id);
    }

} else {

    while(2)
    {
		lock_semaphore ( sem_id);
		i++;
		(*(int*)shared_mem) = i;
		printf("Родитель, %d\n", i);
		unlock_semaphore ( sem_id);
		sleep ( 1);
    }

}

//if((semctl(sem_id,1,IPC_RMID)) == -1)
//perror("semctl");
exit(0);
} 

//fuction for lock semaphore
inline void lock_semaphore ( const int sem_id)
{
operations_with_semaphore[0].sem_num = 0;
operations_with_semaphore[0].sem_op = -1;
operations_with_semaphore[0].sem_flg = SEM_UNDO;
semop ( sem_id, operations_with_semaphore, 1);
//lock semaphore
};
//------------------------------------------------------------------------------

//fuction for unlock semaphore
inline void unlock_semaphore ( const int sem_id)
{
operations_with_semaphore[0].sem_num = 0;
operations_with_semaphore[0].sem_op = 1;
operations_with_semaphore[0].sem_flg = SEM_UNDO;
semop ( sem_id, operations_with_semaphore, 1);
//unlock semaphore
};

Пока родитель пишет в шаренкю память потомок не имеет к ней доступа,
и пока потомок читает из памяти родетель не может в нее писать, он заблокирован.

stalcker
()
Ответ на: комментарий от anonymous

    while(2)
    {
		lock_semaphore ( sem_id);
		i++;
		(*(int*)shared_mem) = i;
		printf("Родитель, %d\n", i);
		unlock_semaphore ( sem_id);
		sleep ( 1);
    }

да, кстати, sleep ( 1)  для наглядности

stalcker
()
Ответ на: комментарий от anonymous

Поставть внутри одного из while например sleep ( 10), затем

$ps -Al

и ты увидишь, что один процесс спит а второй заблокирован. Можно, например, в начало шареной памяти писать метку, отец пишет 1 и проверяет если она не сброшена в 0 значит потомок не прочитал данные и засыпает, или делает другую полезную работу, потомок проверяет если записана 1 то данные обновились и после чтения сбрасывает значение в 0, если данные не обновились, сам придумай.

С помощью семафоров ты не можешь контролировать очередность поступления задач на процессор, ты можешь только регулировать доступ к ресурсу и если ресурс занят(не готов) то процесс можно заблокировать.

stalcker
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.