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


Автор: rthsobakas 29.9.2008, 17:11


Задача следюущая: 
Процесс 1 открывает фаил и порождает потомков 2 и 3 , процесс 1 с интервалом в 1 сек (через alarm) по очереди посылает N сигналов sig1 процессам 2 и 3 которые по каждому сигналу пишут в общий фаил по M чисел. Потом процесс 1 посылает потомкам сигнал sig2, процесы завершаются. Процесс 1 считывает данные из фаила и выводит на экран.

Как посылается сигнал потомкам? 
Типо потомок так создается:
int pid2;
pid2=fork();
if (pid2==0){
}
Зачем тут условие? и Что оно озночает(Почему именно с нулем сравнивает)? 
Что такое Alarm и как через него послать сигнал?



И ещё скажите что означают следующие записи?
 1)  struct sigaction action;
 2)  action.sa_handler = &parent_handler;

Автор: MAKCim 29.9.2008, 21:06
rthsobakas, 
прочитайте сначала какую-нибудь литературу
а лучше
man 2 fork
man 2 sigaction
man 2 alarm
man 2 kill

Автор: rthsobakas 29.9.2008, 21:53
ну прочитал. 
fork -порождает процесс
Например 1 процесс породил 2 процесс. При успешном завершении родителю возвращается PID процесса-потомка, а процессу-потомку возвращается 0. Типо условие нужно для проверки создался он или нет, иначе можно без условия сделать ,но прога работать наверно работать не будет.
Код

int main(){
pid_t pid2;
pid2=fork();
if (pid2==0){
}}



sigaction int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
Системный вызов sigaction используется для изменения действий процесса при получении соответствующего сигнала. 

alarm это типо слипа, задержка вообщем,

 kill завершить процесс. kill посылает указанный сигнал указанному процессу. Если не указано ни одного сигнала, посылается сигнал TERM. Сигнал TERM завершит те процессы, которые не обрабатывают его приход. Для других процессов может быть необходимым послать сигнал 9, поскольку этот сигнал перехватить нельзя.
Типо он используется для передачи сигнала потомку,тока не понятно как,,,



Ну я прогу начал писать,но в фаил она не забивает символы почему то... Вернее не почему то а потому что я хз как правильно сигнал отправить.
Код

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

FILE *fp;

void hadler(nsig){
char c;
int i,m=5;
for (i=0;i<m;i++){
c=random(100);
putc(c,fp);
}
}

void vi(void){
int st;
wait(&st);
}

void main(void){
int pid2,pid3,n=10,i;
char c;
fp=fopen("test.txt","w+");

printf("Starting process 1, pid=%d\n",getpid());

//2 потомок создали
pid2=fork();
if (pid2==0)
{
printf("Starting process 2,pid=%d\n",getpid());
for (i=0;i<n;i++){
//отправили сигнал для  ввода символов
alarm(1);
signal(SIGALRM,hadler);
}
//сигнал для завершения
signal(SIGINT,vi);
}


pid3=fork();
if (pid3==0)
{
printf("Starting process 3,pid=%d\n",getpid());
for (i=0;i<n;i++){
alarm(1);
signal(SIGALRM,hadler);
}
signal(SIGINT,vi);
}

while (!feof(fp)){
c=getc(fp);
printf("%c",c);
}

signal(SIGINT,vi);
printf("Process 1 ended\n");
fclose(fp);
exit(0);
}

Автор: lamao 29.9.2008, 22:18
Вообще-то судя по постановке задачи необходимости в порождениях процессов нет. Здесь целесообразно использовать потоки как минимум по трем причинам:
1) Создание потока на порядок дешевле чем создание процесса
2) Так как первоначальный процесс контролирует выполнение дочерных процессов и имеет место межпроцесное взаимодействие.
3) Запрограммировать все это будет проще и читабельнее именно с использовнием потоков.

В общем я бы в рамках одного родительского процесса создавал бы все эти сервисные потоки.
Детальнее нужно читать в 
Код

man pthread


Автор: MAKCim 30.9.2008, 00:12
Код

#define N 10
#define M 20

static sigset_t set;

static int fd;

static void handle()
{
    int i;
    char buffer[32];
    for (i = 0; i < M; ++i) {
        sprintf(buffer, "%u\n", i);
        flock(fd, LOCK_EX);
        write(fd, buffer, strlen(buffer));
        flock(fd, LOCK_UN);
    }
}

static void child_routine()
{
    int number, flags, count, ready;
    struct timespec timespec = {
        .tv_sec = 0,
        .tv_nsec = 0
    };    
    flags = 0;
    count = 0;
    ready = 0;
    for (;;) {
        switch (sigtimedwait(&set, NULL, &timespec)) {
            default:
                break;
            case SIGUSR1:
                ++count;
                break;
            case SIGUSR2:
                flags = 1;
        }
        for (; ready < count; ++ready) handle();
        if (count == M && flags) break;
    }
}

static void read_file()
{
    int i;
    lseek(fd, 0, SEEK_SET);
    FILE *f = fdopen(fd, "r+");
    while (fscanf(f, "%u", &i) != EOF) printf("%u\n", i);
    close(fd);
}

int main()
{
    pid_t pids[2];
    sigset_t __set;
    int i;
    if ((fd = open("data", O_CREAT | O_RDWR | O_EXCL)) < 0) {
        perror("open");
        return -1;
    }
    sigaddset(&set, SIGUSR1);
    sigaddset(&set, SIGUSR2);
    sigprocmask(SIG_BLOCK, &set, NULL);
    for (i = 0; i < 2; ++i) {
        if ((pids[i] = fork()) == 0) {
            child_routine();
            _exit(0);
        } else if (pids[i] < 0) {
            perror("fork");
            for (--i; i >= 0; --i) kill(pids[i], SIGKILL); // destroy created processes
            return -1;
        }
    }
    sigemptyset(&__set);
    sigaddset(&__set, SIGALRM);
    for (i = 0; i < 2; ++i) {
        int count = N, sig;
        for (; count; --count) {
            alarm(1);
            sigwait(&__set, &sig)
            kill(pids[i], SIGUSR1);
        }
    }
    for (i = 0; i < 2; ++i) kill(pids[i], SIGUSR2);
    for (i = 0; i < 2; ++i) waitpid(pids[i], NULL, 0);
    read_file();
    return 0;
}

Автор: rthsobakas 30.9.2008, 09:21
ммм... так то спасибо конечно, но хотелось бы разобраться самому( к тому же код компилится с ошибками)

Может есть специальные книги, авторы какие нибудь которые на примерах показывают? Просто рылся в яндексе,гугле там в основном статьи небольшие, причем проги  простые(процесс породил потомка и  убил его)... Или наоборот навароченные

Автор: rthsobakas 30.9.2008, 12:32
Вообщем я вроде понял как сигнал процессу передать

Код


#include <stdio.h>
#include <signal.h>

FILE *fil;
int count=0;

void catcher1()
{
int i;
fil=fopen("test.txt","a");
count++;
printf("Сигнал%d:",count);fprintf(fil,"Сигнал%d:",count);
for (i=0;i<M;i++){printf("%d",count);fprintf(fil,"%d",count);}
printf("\n");fprintf(fil,"\n");
fclose(fil);
}



int main(){
pid_t pid2,pid3;
int st,j;
fil=fopen("test.txt","w+");
fclose(fil);
printf(" начало...\n");
pid2=fork();
if (pid2==0){
signal(SIGUSR1,catcher1);
}


pid3=fork();
if (pid3==0){
signal(SIGUSR1,catcher1);
}


kill(pid2,SIGUSR1);
kill(pid3,SIGUSR1);

printf(" Программа закончена...");
return 0;
}



kill(pid2,SIGUSR1);
kill(pid3,SIGUSR1);  
ими сигнал типо передается 2 и 3 потомку, а signal(SIGUSR1,catcher1); типо в потомке ловится.Тока результат разный получается почему то хз почему....((((

user@user:~/Desktop> lab4
 начало...
Сигнал1:1111111111
 Программа закончена...Определяемый пользователем сигнал 1
user@user:~/Desktop> Сигнал1:1111111111
Сигнал2:2222222222
Сигнал3:3333333333
 Программа закончена...Сигнал1:1111111111
Сигнал2:2222222222
 Программа закончена...   

Вот это не понятно почему появляется, когда прога заработала
Определяемый пользователем сигнал 1
user@user:~/Desktop> 


Почему 3 вызов кэтчера происходит тоже не ясно Сигнал3:3333333333

И почему повотрно прога выполняется ?
 Программа закончена...Сигнал1:1111111111
Сигнал2:2222222222
 Программа закончена...  


Вообщем кто как думает в чем касяк?Я думал проблема в том что процесс потомок не завершается и выполняется рандомом  ещё несколько раз и использовал типо Wait(&st) (написано в литературе что он для завершения процесса типо), но он вроде как ваще не влияет на исход результата...

По логике должен получатся результат:

user@user:~/Desktop> lab4
 начало...
Сигнал1:1111111111
Сигнал2:2222222222
 Программа закончена...

Потом если это в цикле сделать например 2 раза(kill(pid2,SIGUSR1);kill(pid3,SIGUSR1);  )

То  получится должно
user@user:~/Desktop> lab4
 начало...
Сигнал1:1111111111
Сигнал2:2222222222
Сигнал3:3333333333
Сигнал4:4444444444
 Программа закончена...


Автор: MAKCim 30.9.2008, 12:45
Цитата(rthsobakas @  30.9.2008,  09:21 Найти цитируемый пост)
ммм... так то спасибо конечно, но хотелось бы разобраться самому( к тому же код компилится с ошибками)

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

Автор: rthsobakas 30.9.2008, 13:02
сначала заставь код компилироваться, а потом задавай вопросы, что не понятно
ну там мелкие касяки  были с точкой и запятой я их убрал , с ворнингами но скомпилилось. Ну и что код все равно сложный слишком. Сложные типы, структуры какие то...

Это то же самое что какой нить чувак попросил бы привести пример сложения двух чисел на паскале
что то типо
Код

uses crt;
var
a,b,sum:byte;
begin
 sum:=a+b;
end.

 а ему на встроенном асме через сопроцессор показали)))
Он бы тоже офигел немного наверно)))

Прочитай моё предпоследнее сообщение(это последнее), там я выразил суть проблемы. Если хочешь помочь лучше скажи что в моем(последнем) коде не так... И все

Автор: MAKCim 30.9.2008, 13:07
rthsobakas, 
у тебя мешанина с выводом в файл
открывай файл в main() и делай синхронизацию при записи через flock()

Автор: rthsobakas 30.9.2008, 13:45
ммммм сделал как у тебя

Код

#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#define N 3
#define M 10

int count=0;
static int fd;
void catcher1()
{
int i;
count++;
 char buffer[20]={"f"};

    flock(fd, LOCK_EX);
    for (i = 0; i < M; ++i) {
        flock(fd, LOCK_EX);
        write(fd, buffer,strlen(buffer));
        flock(fd, LOCK_UN);}
flock(fd, LOCK_EX);
write(fd, "\n");
flock(fd, LOCK_UN);
}




int main(){
pid_t pid2,pid3;
int st,j;

    if ((fd = open("AAAAA.txt", O_CREAT | O_RDWR | O_EXCL)) < 0) {
        perror("open");
        return -1;
    }

printf(" начало...\n");
pid2=fork();
if (pid2==0){
signal(SIGUSR1,catcher1);
}


pid3=fork();
if (pid3==0){
signal(SIGUSR1,catcher1);
}


kill(pid2,SIGUSR1);

kill(pid3,SIGUSR1);
close(fd);
printf(" Программа закончена...");
return 0;


в AAAAA.txt"
результат
ffffffffff
ffffffffff
ffffffffff
ffffffffff

То есть 4  раза он шпарит кэтчер,а надо два потому что
kill(pid2,SIGUSR1);
kill(pid3,SIGUSR1);
тока два вызова

И ещё почему то  стали нужны права супер пользователя чтобы фаил посмотреть(((

Добавлено через 2 минуты и 26 секунд
может где то wait надо написать? такое чувство что потомки повторяются

Автор: MAKCim 30.9.2008, 14:46
Код

#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#define N 3
#define M 10
int count=0;
static int fd;
void catcher1()
{
int i;
count++;
 char buffer[20]={"f"};
 flock(fd, LOCK_EX);
    for (i = 0; i < M; ++i) {
        write(fd, buffer,strlen(buffer));
   }
write(fd, "\n");
flock(fd, LOCK_UN);
}
int main(){
pid_t pid2,pid3;
int st,j;
    if ((fd = open("AAAAA.txt", O_CREAT | O_RDWR | O_EXCL)) < 0) {
        perror("open");
        return -1;
    }
printf(" начало...\n");
pid2=fork();
if (pid2==0){
signal(SIGUSR1,catcher1);
while (1) pause();
}
pid3=fork();
if (pid3==0){
signal(SIGUSR1,catcher1);
while (1) pause();
}
kill(pid2,SIGUSR1);
kill(pid3,SIGUSR1);
close(fd);
printf(" Программа закончена...\n");
return 0;
}

Автор: rthsobakas 30.9.2008, 15:03
капец , я так и знал что где то подстава
оказывается все дело в
Код

while (1) pause();


Ещё один вопрос и я отвалю)))


Fork создает процесс, а как процесс убить? Просто я читал про wait и  exit они типо убивать должны. Я че то с ними экспериментировал , кроме Ворнингов компилятора они ниче не изменили...

То есть смотри

если я хочу убить pid2 и pid3, то опять по аналогии писать надо KILL(pid2,SIGUSR2);(в родителе) и signal(SIGUSR2,ubit); (в потомке) и писать ф-ию UBIT, а в ней exit(0);?
и в родителе вместо return 0 писать exit(0)? так получается?

Автор: MAKCim 30.9.2008, 15:29
Цитата(rthsobakas @  30.9.2008,  15:03 Найти цитируемый пост)
Fork создает процесс, а как процесс убить?

в родителе wait()
в дочернем процессе _exit()

Автор: rthsobakas 5.10.2008, 14:32
Вообщем вот конечный вариант

Код

/*Процесс 1 открывает фаил и порождает 2 и 3 потомка, процесс 1 с интервалом в 1 сек по очереди посылает Н сигналов птоомкам 2 3,
которые пишут М символов в фаил,
Потом процесс убмвает потомков*/
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#define N 3
#define M 10
int count=0;
static int fd;
FILE *f;

void catcher1()
{
int i;
count++;
 char ch=(char)(count+100);
 char buffer[20]={ch};
 flock(fd, LOCK_EX);
    for (i = 0; i < M; ++i) {
        write(fd, buffer,strlen(buffer));
   }
write(fd, "\n");
flock(fd, LOCK_UN);
}

void catcher2()
{
wait();
}


/*Главная функия*/
int main(){
pid_t pid2,pid3;//процессы
int st,j;
char c;
// открываем фаил
    if ((fd = open("AAAAA.txt", O_CREAT | O_RDWR | O_EXCL)) < 0) {
        perror("open");
        return -1;
    }
printf(" Begin...\n");
pid2=fork();//создали потомка 1
if (pid2==0){
signal(SIGUSR1,catcher1);
signal(SIGUSR2,catcher2);
while (1) pause();
}
pid3=fork();//создали потомка 2
if (pid3==0){
signal(SIGUSR1,catcher1);
signal(SIGUSR2,catcher2);
while (1) pause();
}
int i;
for (i = 0; i < N; ++i){
printf(" wait...%d\n",i);
sleep(1);
kill(pid2,SIGUSR1);//послали 1 сигнал
printf(" wait...%d\n",i);
sleep(1);
kill(pid3,SIGUSR1);//послали 2 сигнал
}
kill(pid2,SIGUSR2);//послали 1 сигнал
kill(pid3,SIGUSR2);//послали 2 сигнал

printf(" Program over...\n");
close(fd);

if ((f=fopen("AAAAA.txt","r"))==0) {printf("file not open!\n");return 0;}
while (!feof(f))
{
c=getc(f);printf("%c",c);
}
fclose(f);
return 0;
} 



Вообщем все вроде хорошо, только не знаю почему ,но в конце при чтении фаила и вывода на экран каждого символа последняя строка(фаила) не читается. Причем если сделать другую прогу и там попробывать этот фаил прочитать, то все прочтется нормально...Пробывал for`ом каждый символ выводить , после 5 строки  нули выводит, хз почему...  

Автор: MAKCim 6.10.2008, 08:27
rthsobakas, 
у меня работает
да, в catcher2 нужен _exit(), а не wait()

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