LINUX.ORG.RU

Помогите разобраться с программой!

 , ,


0

3

Вот задание. Процесс 1 открывает файл, порождает потомка 2, пишет в файл N байт и посылает сигнал SIG1 процессу 2. Процесс 2 по сигналу SIG1 читает данные, выводит их на экран и завершается. Если сигнал от процесса 1 не поступит в течение M секунд, процесс 2 начинает считывать данные по сигналу SIGALRM.
Вот как я пыталась его реализовать:

#include <stdio.h>
#include <signal.h>
#include <wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

int f_in, fd, ppid, pid, N, M, count=0;

void wakeup ()                         //
{
        signal(SIGALRM, wakeup);
        printf("Wake up!\n");
}

void sleeptime (int timeout)
{
        signal(SIGALRM, wakeup);
        alarm(timeout);
        pause();
}

void sigper(int n)
{
        signal(SIGUSR1,sigper);
        printf("KOL-VO BYTE: %d\n", count);
        write(f_in,"1",1);
        kill(pid,SIGUSR1);
}
void sigchail(int n)
{
        signal(SIGUSR1, sigchail);
        write(f_in,"2",1);
        kill(ppid,SIGCHLD);
}
int main(int argc, char*argv[])
{
        ppid=getpid();
        if((f_in= open(argv[1],O_RDONLY))<0){
                ERR("Can't open %s\n",argv[1]);
        }
        N = atoi(argv[2]);

        if (pid=fork()<0){
                ERR("Can't fork");
        }
        else if(fork_pid>0){
                signal(SIGUSR1,sigper);
                kill(pid,SIGUSR1);
        }
        else {
                pause();
                signal(SIGUSR1,sigchail);
                _exit(-1);
        }
        read(1,&inp,1);
        putchar(inp);
        close(f_in);
        printf("1");
        return(0);
}

Заранее благодарю за помощь!

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

Ну если попросили помощи, значит как-то не получается, а сессия уже на носу. А в ВУЗе еще и математических предметов куча. В общем, тут SOS, zeit not и все такое...

metawishmaster ★★★★★
()

в прошлом варианте был косяк, и escape-символ тут больше не приходит, что есть хорошо :)

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

int f_in, pid, N, M;

void stopfn(int n)
{
	close(f_in);
	exit(0);
}

void sigper(int n)
{
	char c, *sig;

	if (n != SIGUSR1 && n != SIGALRM)
		return;

	c = n == SIGUSR1 ? '\0' : '\n';
	sig = n == SIGUSR1 ? "USR1" : "ALRM";

	printf("%cSIG%s\n", c, sig);

	while (read(f_in, &c, 1) == 1)
		write(1, &c, 1);

	lseek(f_in, 0, SEEK_SET);
	kill(getppid(), SIGUSR1);
	printf("\n");
}

int main(int argc, char *argv[])
{
	int i = 0;
	ssize_t ret;
	char inp;

	if (argc < 4) {
		printf("error: insuffucient arguments\n");
		return 1;
	}

	if ((f_in = open(argv[1], O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) {
		printf("Can't open %s\n", argv[1]);
		return 1;
	}
	N = atoi(argv[2]);
	M = atoi(argv[3]);

	if ((pid = fork()) < 0) {
		printf("Can't fork\n");
	} else if (pid == 0) {
		signal(SIGUSR1, sigper);
		signal(SIGALRM, sigper);
		alarm(M);
		pause();
	} else {
		signal(SIGUSR1, stopfn);
		do {
			ret = read(0, &inp, 1);
			if (inp == '\r' || inp == '\n' || ret <= 0)
				break;
			if (i < N) {
				write(f_in, &inp, 1);
				i++;
			}
		} while (ret > 0);
		lseek(f_in, 0, SEEK_SET);
		kill(pid, SIGUSR1);
	}
	close(f_in);

	return (0);
}

metawishmaster ★★★★★
()
Последнее исправление: metawishmaster (всего исправлений: 4)

ну и вот еще - я забыл проверить входные параметры, поэтому после

N = atoi(argv[2]);                                                              
M = atoi(argv[3]);

(до fork'a) вставь
if (M < 0 || N < 0) {                                                           
    printf("error: incorrect arguments\n");                                     
    close(f_in);                                                                
    return 1;                                                                   
}                                                                               
                                                                                    
if (M == 0) {                                                                   
    while (read(f_in, &inp, 1) == 1)                                            
        write(1, &inp, 1);
    close(f_in);                                                  
    return 0;                                                                   
}

кроме того, в коне функции sigper
lseek(f_in, 0, SEEK_SET);

ни на что не влияет, можно удалить дабы не было лишних вопросов

metawishmaster ★★★★★
()
Последнее исправление: metawishmaster (всего исправлений: 2)

в идеале, конечно, лучше переставить выражения в main от объявления переменных до fork(), чтоб не открывать файл, если параметры плохие:

	char inp;

	if (argc < 4) {
		printf("error: insuffucient arguments\n");
		return 1;
	}
	N = atoi(argv[2]);
	M = atoi(argv[3]);

	if (M < 0 || N < 0) {
		printf("error: incorrect arguments\n");
		return 1;
	}

	if ((f_in = open(argv[1], O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) {
		printf("error: can't open %s\n", argv[1]);
		return 1;
	}

	if (M == 0) {
		while (read(f_in, &inp, 1) == 1)
			write(1, &inp, 1);
		close(f_in);
		return 0;
	}

	if ((pid = fork()) < 0) {
		printf("error: can't fork\n");
	} else if (pid == 0) {


p.s. и не молчи как партизан - спрашивай, если что не понятно :)

metawishmaster ★★★★★
()
Последнее исправление: metawishmaster (всего исправлений: 4)
Ответ на: комментарий от metawishmaster

p.s. и не молчи как партизан - спрашивай, если что не понятно :)

Он уже давно убежал, испугавшись этого сижного ада, и я не виню его, любой на его месте поступил бы так, ведь не всем хочется до конца жизни вручную расставлять malloc и free в правильном порядке, трясущимися руками собирать по кусочкам лопнувшие буфера, зашивать треснувший по швам стек, чтобы потом все равно оказаться втоптанным в грязь более дерзким и молодым самцом (Rust™).

Разорванный Флакон

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

разорванный, когда запилишь поддержку Windows XP в Rust или KolibriOS или PS1 или ещё 100500 платформ где раста нет и никогда не будет, а сишка есть.

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

разорванный, когда запилишь поддержку Windows XP в Rust или KolibriOS или PS1 или ещё 100500 платформ где раста нет и никогда не будет, а сишка есть.

Мертвым платформам – мертвый язык. Пока Rust будет работать на Windows 10+, Xbox Two, Fuchsia, Redox OS, одним словом, на платформах XXII века, ты со своей сижкой оставайся на окаменевших системах, я тебе, словно нищему на паперти, сверху накину еще и PS2 с PS3, можешь и их занести в свой список «1000 и 1 платформа, где сижка всех порвет, мамой клянусь!».

Разорванный Флакон

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



Вот как я пыталась его реализовать:
...
Заранее благодарю за помощь!


Помогу чем смогу.
https://www.google.ru/search?newwindow=1&source=hp&ei=bPqwXp-QBeOFmwX...


ничего умнее в голову не пришло? а! в детском садике же сейчас тоже удаленка! пнятно :)

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

Спасибо большое за помощь. Я в этом языке совсем новичок,поэтому многое для меня непонятно, а делать, к сожалению, надо. Если возможно, можете пояснить, почему

c = n == SIGUSR1 ? '\0' : '\n'; 
sig = n == SIGUSR1 ? "USR1" : "ALRM";

printf("%SIG%s\n", c, sig);

нельзя заменить на

	printf("SIG%s\n", n == SIGUSR1 ? "USR1" : "ALRM");

и зачем вообще *sig?

И еще при работе программы будет выводиться во эта строчка?

 	printf("error: insuffucient arguments\n");

Возможно, вопросы невероятно тупые, извините, если что)

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


можете пояснить, почему

c = n == SIGUSR1 ? '\0' : '\n'; 
sig = n == SIGUSR1 ? "USR1" : "ALRM";

printf("%SIG%s\n", c, sig);

нельзя заменить на
printf("SIG%s\n", n == SIGUSR1 ? "USR1" : "ALRM");


да, вообще, можно, но тогда, если начать вводить строку, но не успеть нажать enter до таймаута, будут получаться некрасивости типа такой

sbauer@metabook ~/devel/tasks$ ./t_xxx t_xxx.txt 3 1
qwddeSIGALRM
MetallicA

вместо
sbauer@metabook ~/devel/tasks$ ./t_xxx t_xxx.txt 3 1
qwdde
SIGALRM
MetallicA

но, действительно, лучше заменить (и убрать sig), чтоб препод ничего не заподозрил :)
[upd]
и, вообше, если вывод имени сигнала в условии не предусмотрен, но можно и printf убрать, но так получается нагляднее и красивее =)
[/upd]


И еще при работе программы будет выводиться во эта строчка?

printf("error: insuffucient arguments\n");


она выводится только если количество параметров меньше трех


Возможно, вопросы невероятно тупые, извините, если что)


такое бывает, когда что-то новое, все ок :)

metawishmaster ★★★★★
()
Последнее исправление: metawishmaster (всего исправлений: 8)
Ответ на: комментарий от anonymous

Windows 10+, Xbox Two, Fuchsia

Written in С, С++

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


Я в этом языке совсем новичок,поэтому многое для меня непонятно, а делать, к сожалению, надо.


только подумал, у тебя сейчас нет возможности доступа к какой-нить unix-like системе, чтоб проверять программу?

metawishmaster ★★★★★
()
Последнее исправление: metawishmaster (всего исправлений: 1)
Ответ на: комментарий от metawishmaster

только подумал, у тебя сейчас нет возможности доступа к какой-нить unix-like системе, чтоб проверять программу?

со вчерашнего дня возможность доступа появилась

beginner99
() автор топика
Ответ на: комментарий от metawishmaster

А можете пояснить эти конструкции?

while (read(f_in, &c, 1) == 1)

    write(1, &c, 1);

 

  lseek(f_in, 0, SEEK_SET);

  kill(getppid(), SIGUSR1);

  printf("\n");

}

 

int main(int argc, char *argv[])

{

  int i = 0;

  ssize_t ret;

  char inp;


и

signal(SIGUSR1, stopfn);

    do {

      ret = read(0, &inp, 1);

      if (inp == '\r' || inp == '\n' || ret <= 0)

        break;

      if (i < N) {

        write(f_in, &inp, 1);

        i++;

      }

    } while (ret > 0);

    lseek(f_in, 0, SEEK_SET);
в первой, получается, мы записываем в файл результат ввода, пока он открыт и посылаем сигнал предку?

а во второй мы выводим в консоль?

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

в первой, получается, мы записываем в файл результат ввода

Наоборот: выполняется чтение из файла и запись в fd1 (stdout). Наглядный пример, почему magic numbers — зло.


а во второй мы выводим в консоль?

Нет: во второй идёт чтение из fd0 (stdin) в файл

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

сорри, до утра разбирался со всякой фигней

можете пояснить эти конструкции?

ближе к тому, что сказал XMs :)

в [1] читаю из файла (f_in) по символу и вывожу в поток стандартного вывода (1), а затем, когда символ не прочитался (или конец файла, или какая-то ошибка) посылаю сигнал SIGUSR1 родителю, при обработке которого тот закрывает файл и завершается.

в [2] родитель сначала привязыват сигнал SIGUSR1 в функции, в которой он закроет f_in и выйдет из программы, а затем читает из потока стандартного ввода (0) символ.
если символ - перевод строки или мы не прочитали (или ошибка), то вываливаемся из цикла
если все ок и мы еще не превылиси лимит символов (который задали вторым аргументом программе), то записываем символ в файл. и так пока read говорит, что у нас получилось прочитать.
затем переводим «файловый указатель» на начало файла f_in, чтобы потомок при чтетии не уткнулся в конец файла и посылаем сигнал потомку, чтобы он прочитал файл f_in.

metawishmaster ★★★★★
()
Последнее исправление: metawishmaster (всего исправлений: 3)
Ответ на: комментарий от beginner99


Спасибо огромное!!


да не за что же, это ж не задачка с ICPC, в конце концов :)

сейчас главное, чтоб программка работала, и тебе все было понятно

metawishmaster ★★★★★
()
Последнее исправление: metawishmaster (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.