reklama

[C] Ako prečíst dáta zo súboru a zapísať je do PIPE-y když proces prijme signál?

Momentálne mám tento kód a nefunguje správne:

Kód: [Vybrat]
#define _POSIX_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>

int fd, P1;

void handler(int signum)
{
char buff[151], c;
size_t i;
for (i = 0; (c = getc(fd)) != EOF; i++) {
buff[i] = c;
}
buff[i+1] = '\0';

write(P1, buff, strlen(buff));
}

int main(int argc, char *argv[])
{
fd = open("p1.txt", O_RDONLY);
(void)signal(SIGUSR1, handler);
P1 = atoi(argv[1]);

const char* textmsg = "P1 SA HLASI KU SLUZBE!";
printf("%s\n", textmsg);

kill(getppid(), SIGUSR1);

while (1)
{
sleep(5);
}

return 0;
}

reklama


Nechtěl jste místo getppid použít getpid?

Nechtěl jste místo getppid použít getpid?

nie, nechtěl (aspoň myslím).

konkrétnejšie sa jedná o toto zadanie:

http://it4kt.cnl.sk/c/os/2016/problemset.03.html

ktoré riešim.

.

Nedělej ten zápis v signal handleru. V tom hlavním cyklu prostě počkej na signál a až dorazí, tak proveď zápis.
getc je pro použití s FILE*, ne s fd (to ti překladač neřve?). A máš zapsat jen jedno slovo.

Nedělej ten zápis v signal handleru. V tom hlavním cyklu prostě počkej na signál a až dorazí, tak proveď zápis.
getc je pro použití s FILE*, ne s fd (to ti překladač neřve?). A máš zapsat jen jedno slovo.

pôvodne som mal v handleru len ten write(); prekladač mi to momentlne rve, predtým som mal iný kód bez getc(), nefungovalo i tak.
Potrebujem zapísať postupne celý obsah súboru, kde je 10 riadkov textu.

reklama


tak nejde ani:

Kód: [Vybrat]
#define _POSIX_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>

int fd, P1;
char input[151];

void handler(int signum)
{
write(P1, input, strlen(input));
}

int main(int argc, char *argv[])
{
fd = open("p1.txt", O_RDONLY);
char buffer;
int lenght = 0;

while (1)
{
read(fd, &buffer, 1);
input[lenght] = buffer;
input[lenght + 1] = '\0';
if (buffer != '\n')
{
lenght++;
}
else
{
break;
}
}

P1 = atoi(argv[1]);
(void)signal(SIGUSR1, handler);

const char* textmsg = "P1 SA HLASI KU SLUZBE!";
printf("%s\n", textmsg);

kill(getppid(), SIGUSR1);

while (1)
{
sleep(5);
}

return (0);
}
« Poslední změna: 06. 01. 2019, 18:34:25 od Gabriel Mlocik »

Neviditelný

Pokud chceš posílat signály sám sobě, potřebuješ getpid(). Protože ale to cvičení řeší komunikaci mezi procesy, chceš ve skutečnosti signalizovat mezi rodiči a potomky. Funguje třeba toto:

Kód: [Vybrat]
#define _POSIX_C_SOURCE 199506L

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

static int pipefd[2];
static sigset_t sset;

static
void write_to_pipe()
{
size_t idx = 0;
int sigret;
FILE *fh;
char buf[151];

close(pipefd[0]);

if (sigwait(&sset, &sigret) != 0)
_exit(EXIT_FAILURE);
if (sigret != SIGUSR1)
_exit(EXIT_FAILURE);

fh = fopen("p1.txt", "r");
if (fh == NULL)
_exit(EXIT_FAILURE);

while (idx < sizeof(buf) - 1) {
if (fread(buf + idx, 1, 1, fh) != 1)
_exit(EXIT_FAILURE);

idx++;
if (buf[idx-1] == '\n')
break;
}
buf[idx + 1] = '\0';

write(pipefd[1], buf, idx);
close(pipefd[1]);

_exit(EXIT_SUCCESS);
}

static
void read_from_pipe()
{
char buf;

while (read(pipefd[0], &buf, 1) > 0)
putchar(buf);

close(pipefd[0]);
}

int main(int argc, char *argv[])
{
const char* textmsg = "P1 SA HLASI KU SLUZBE!";
pid_t child;

sigemptyset(&sset);
sigaddset(&sset, SIGUSR1);
sigprocmask(SIG_BLOCK, &sset, NULL);

if (pipe(pipefd) < 0) {
perror("Failed to create pipe");
exit(EXIT_FAILURE);
}

puts(textmsg);

child = fork();
if (child < 0) {
perror("Forking failed");
exit(EXIT_FAILURE);
}

if (child == 0) {
write_to_pipe();
} else {
close(pipefd[1]);
kill(child, SIGUSR1);
read_from_pipe();
wait(NULL);
}

puts("All done");

return EXIT_SUCCESS;
}

Pokud chceš posílat signály sám sobě, potřebuješ getpid(). Protože ale to cvičení řeší komunikaci mezi procesy, chceš ve skutečnosti signalizovat mezi rodiči a potomky. Funguje třeba toto:

Kód: [Vybrat]
#define _POSIX_C_SOURCE 199506L

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

static int pipefd[2];
static sigset_t sset;

static
void write_to_pipe()
{
size_t idx = 0;
int sigret;
FILE *fh;
char buf[151];

close(pipefd[0]);

if (sigwait(&sset, &sigret) != 0)
_exit(EXIT_FAILURE);
if (sigret != SIGUSR1)
_exit(EXIT_FAILURE);

fh = fopen("p1.txt", "r");
if (fh == NULL)
_exit(EXIT_FAILURE);

while (idx < sizeof(buf) - 1) {
if (fread(buf + idx, 1, 1, fh) != 1)
_exit(EXIT_FAILURE);

idx++;
if (buf[idx-1] == '\n')
break;
}
buf[idx + 1] = '\0';

write(pipefd[1], buf, idx);
close(pipefd[1]);

_exit(EXIT_SUCCESS);
}

static
void read_from_pipe()
{
char buf;

while (read(pipefd[0], &buf, 1) > 0)
putchar(buf);

close(pipefd[0]);
}

int main(int argc, char *argv[])
{
const char* textmsg = "P1 SA HLASI KU SLUZBE!";
pid_t child;

sigemptyset(&sset);
sigaddset(&sset, SIGUSR1);
sigprocmask(SIG_BLOCK, &sset, NULL);

if (pipe(pipefd) < 0) {
perror("Failed to create pipe");
exit(EXIT_FAILURE);
}

puts(textmsg);

child = fork();
if (child < 0) {
perror("Forking failed");
exit(EXIT_FAILURE);
}

if (child == 0) {
write_to_pipe();
} else {
close(pipefd[1]);
kill(child, SIGUSR1);
read_from_pipe();
wait(NULL);
}

puts("All done");

return EXIT_SUCCESS;
}

ďakujem, vyskúšam.

tak to nefunguje... s týmto kódom žiaľ program bežal vyše 2 minút. A limit v testoch sú práve 2 minúty. Okrem toho dostávam hlášku:


Segment 1024 nemozno vymazat!

Kód: [Vybrat]
----------------------------------------------------
Runner:Spustam:
runner: Maximalny cas behu 120 sekund
Runner:kill
runner: Skutocny cas behu:121 s
runner: ukoncujem ostatne procesy:
Segment 1024 nemozno vymazat!
runner: Ukoncenych 3 procesov
Segment 1024 nemozno vymazat!
runner:OK
runner:vraciam 130

Neviditelný, máte Github? že by som Vás pridal do repa, aby ste sa mi na to pozrel.

Neviditelný

To sice mám ale popravdě se mi moc nechce se v tom vrtat, protože mám dost vlastní práce:) Zdá se to jako nějaká zápočtová úloha, nebude tedy jednodušší zeptat se vyučujících? Od toho tam snad jsou, ne?

Jinak ten můj demo kód je jen primitivní ukázka, jak forknout proces, čekat na signál a poslat data rourou rodiči. Asi nebude úplně možné to jen tak zkopírovat a čekat, že to bude okamžitě chodit. BTW to čekání na zamaskovaný signál pomocí sigwait() je pro jakoukoliv netriviální operaci dost dobrý nápad, protože jednoduché signal handlery jsou náchylné na problémy souběhu...

.

pôvodne som mal v handleru len ten write(); prekladač mi to momentlne rve, predtým som mal iný kód bez getc(), nefungovalo i tak.
Potrebujem zapísať postupne celý obsah súboru, kde je 10 riadkov textu.
Co na tohle říct...

.

Kód: [Vybrat]
printf("hlasim se ke sluzbe\n");
kill(getppid(), SIGUSR1);

while (sigwait(&sset, &sigret) == 0 && sigret == SIGUSR1) {
printf("dostal jsem signal\n");
char slovo[101];
if (fscanf(fh, "%100s", slovo) != 1) {
printf("chyba pri nacitani slova\n");
break;
}

printf("zapisuju slovo %s\n", slovo);
size_t len = strlen(slovo);
if (write(R1, slovo, len) != len) {
printf("chyba pri zapisu slova\n");
break;
}
}

pôvodne som mal v handleru len ten write(); prekladač mi to momentlne rve, predtým som mal iný kód bez getc(), nefungovalo i tak.
Potrebujem zapísať postupne celý obsah súboru, kde je 10 riadkov textu.
Co na tohle říct...

ze to nevím, ze jsem blbej... ja viem čo myslíš, nemusíš mi na to nic říkat,... nehnevám sa, je to pravda...
« Poslední změna: 07. 01. 2019, 12:22:56 od Gabriel Mlocik »

 

reklama