Sida 1 av 1
Få svar tillbaka av ingående FIFO
Postat: 08 maj 2010, 05:17
av dmz
Jag har ett program som pratar med ett annat med hjälp av named pipes (fifo).
Det blir en lite halvtråkig konversation då jag aldrig får några svar dock;
jag vet inte om mina kommandon godtas eller inte, och jag kan heller inte få
någon utdata tillbaka.
Så jag funderar på hur man kan lösa detta?
Applikationen som jag talar med är mplayer, och om jag t.ex skickar kommandot
get_file_name via fifon till mplayer så får jag tillbaka filnamnet i
mplayers fönster - hur kan man få det att skickas någon annanstans?
Jag kör mplayer som en daemon, så jag kan ju aldrig se någon output.
ii har t.ex löst det hela med att ha två pipes; en för input och en för output.
Re: Få svar tillbaka av ingående FIFO
Postat: 08 maj 2010, 22:10
av Konservburk
Två pipes är väl en bra idé, eller? Det kan även röra sig om helt vanliga pipes, det behöver ju inte nödvändigtvis vara fifos.
Det går förstås också att kommunicera åt båda hållen över en enda fifo, men det kräver att alla inblandade är helt överrens om exakt när något ska skickas åt det ena respektive det andra hållet. Därmed inte sagt att det ens går att komma överrens om något sådant med just mplayer utan att gå in och pilla på källkoden. Det vet jag inget om.
Re: Få svar tillbaka av ingående FIFO
Postat: 08 maj 2010, 23:33
av dmz
Min huvudbry är hur jag skall få mplayers output att ta sig till den andra
fifon. Jag insåg dock att detta problem var lättare löst ändå;
Kod: Markera allt
mplayer -quiet -identify -slave -input file=fifo > log
Så är det bara att parse'a utdatan som hamnar i loggen.
Man skulle nog kunna skicka vidare utdatan till en annan pipe också,
jag vet inte vad som blir bäst, än.
Re: Få svar tillbaka av ingående FIFO
Postat: 08 maj 2010, 23:54
av Konservburk
Re: Få svar tillbaka av ingående FIFO
Postat: 09 maj 2010, 07:27
av dmz
fifo_r = read from
fifo_w = write to
Jag fick aldrig din lösning att fungera; troligen på grund av att mplayer
behöver få sin fifo_w utpekad för sig med -slave och -input file.
Anledningen till att jag inte lyckades så bra med två pipes var antagligen
för att jag försökte ha fler än en process att använda dem samtidigt.
Så både lösningen med logfil och två fifos fungerar klockrent.
Jag behöver inte ha fler än en process som läser ifrån fifon, men skulle
gärna vilja kunna skriva till fifo_w från flera ställen samtidigt.
Anledningen är att jag vill kunna styra olika instanser av mplayer
samtidigt.
Jag tar för givet att jag lär skapa en fifo_w för varje instans av mplayer
jag skapar, eller finns det någon bättre lösning?
Re: Få svar tillbaka av ingående FIFO
Postat: 09 maj 2010, 14:49
av Konservburk
dmz skrev:Jag fick aldrig din lösning att fungera; troligen på grund av att mplayer
behöver få sin fifo_w utpekad för sig med -slave och -input file.
Det gick bra när jag testade. Såg du att jag körde med
-idle och att du då behöver öppna en fil i efterhand med
loadfile? Jag körde följande i tre olika terminaler:
dmz skrev:Jag tar för givet att jag lär skapa en fifo_w för varje instans av mplayer
jag skapar, eller finns det någon bättre lösning?
Det beror ju helt på vad du menar med bättre? Du kan inte låta två olika
mplayer läsa från samma fifo eftersom bara den ena kan ta emot det som skickas. Vilken det blir är helt slumpmässigt och beror bara på vilken av dem som lyckas läsa först från fifon.
Som jag nämnde tidigare så kan du i princip använda vanliga pipes istället för fifos så slipper du fundera över vad du ska döpa alla olika fifos till.
Re: Få svar tillbaka av ingående FIFO
Postat: 10 maj 2010, 08:22
av dmz
Konservburk skrev:
Det gick bra när jag testade.
Det gjorde det här också när jag följde instruktionerna.
Konservburk skrev:
Du kan inte låta två olika mplayer läsa från samma fifo eftersom
bara den ena kan ta emot det som skickas. Vilken det blir är helt
slumpmässigt och beror bara på vilken av dem som lyckas läsa först från
fifon.
Precis.
Konservburk skrev:
Som jag nämnde tidigare så kan du i princip använda vanliga pipes istället
för fifos så slipper du fundera över vad du ska döpa alla olika fifos till.
Du får gärna visa hur det skulle gå till med vanliga pipes. Rent spontant
så känns det rätt omständigt.
Angående namngivning så lär något sådant här fungera;
Kod: Markera allt
#!/usr/bin/perl
use strict;
my $spawnPlayer = shift or undef;
if($spawnPlayer) {
require POSIX;
POSIX::mkfifo("app.@{[time]}.fifo", 0666);
}
Och fifon kommer då alltid att ha ett unikt namn för varje process.
Edit: Något som är än bättre är kanske att helt enkelt använda
processens PID. När processen avslutas så tas aktuell fifo bort.
Re: Få svar tillbaka av ingående FIFO
Postat: 10 maj 2010, 09:38
av Substrata
dmz skrev:Jag behöver inte ha fler än en process som läser ifrån fifon, men skulle
gärna vilja kunna skriva till fifo_w från flera ställen samtidigt.
Anledningen är att jag vill kunna styra olika instanser av mplayer
samtidigt.
Jag tar för givet att jag lär skapa en fifo_w för varje instans av mplayer
jag skapar, eller finns det någon bättre lösning?
Process A serialiserar mplayer med omvärlden.
Process B C D ... öppnar socket till A.
Behöver du flera spelare i A kan du göra ett API (list, tell id ...) för länkarna till B C D ... Du kan använda select(2) i A för att koordinera pipes till spelarna och sockets till omvärlden.
Fast du kanske har instanser av mplayer fördelade i ett nätverk?
Re: Få svar tillbaka av ingående FIFO
Postat: 10 maj 2010, 22:37
av Konservburk
dmz skrev:Du får gärna visa hur det skulle gå till med vanliga pipes. Rent spontant
så känns det rätt omständigt.
Typ så här:
Kod: Markera allt
hantera_indatan | mplayer -quiet -idle -slave | hantera_utdatan
Eller kombinera med 1 fifo för att enkelt kunna hantera både indatan och utdatan från samma process:
Kod: Markera allt
hantera_indatan_och_utdatan <fifo | mplayer -quiet -idle -slave >fifo
Men egentligen är väl ett C-program en bra idé här eftersom det ger betydligt större kontroll över hur det hela hanteras. Då kan du dessutom med fördel göra som
Substrata föreslår. Jag tänker mig något i stil med:
Kod: Markera allt
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#define MPLAYER "/usr/bin/mplayer"
void forka_loss_mplayer_som_en_daemon(int in[2])
{
int ut[2];
if (pipe(in) || pipe(ut))
{
exit(EXIT_FAILURE);
}
switch(fork())
{
case 0:
if (
dup2(in[0], STDIN_FILENO) != -1 &&
dup2(ut[1], STDOUT_FILENO) != -1 &&
dup2(ut[1], STDERR_FILENO) != -1 &&
close(in[0]) != -1 &&
close(in[1]) != -1 &&
close(ut[0]) != -1 &&
close(ut[1]) != -1 &&
chdir("/") != -1 &&
setsid() != -1 &&
!fork())
{
char * const argp[] = {
"mplayer", "-quiet", "-idle", "-slave",
(char *) NULL
};
char * const envp[] = {
"HOME=/",
(char *) NULL
};
umask(0);
execve(MPLAYER, argp, envp);
}
case -1:
exit(EXIT_FAILURE);
}
if (close(in[0]) == -1 || close(ut[1]) == -1)
{
exit(EXIT_FAILURE);
}
*in = *ut;
wait(NULL);
}
int main(int argc, char *argv[])
{
int fd[2];
forka_loss_mplayer_som_en_daemon(fd);
ta_hand_om_indatan_och_utdatan(fd);
exit(EXIT_SUCCESS);
}
Jag har utelämnat funktionen
ta_hand_om_indatan_och_utdatan. Den går ju att skriva direkt i C eller så går det att helt enkelt lämna över problemet till något annat program:
Kod: Markera allt
void ta_hand_om_indatan_och_utdatan(int fd[2])
{
execl("/path/to/annat_program_som_tar_hand_om_indatan_och_utdatan", (char *) NULL);
exit(EXIT_FAILURE);
}
Ett väldigt enkelt sånt där annat program skulle då kunna se ut så här:
Det skyfflar då bara vidare allt som kommer på
stdin till pipe:en som går till
mplayer och skyfflar på samma sätt bara vidare att som kommer på pipe:en från
mplayer direkt till
stdout.
Re: Få svar tillbaka av ingående FIFO
Postat: 11 maj 2010, 05:35
av dmz
Heh, vad underbart. Snyggt jobbat allesammans.
Nu är jag tyvärr inte flytande på C men jag har kod som fungerar i Perl och
det är inga konstigheter att översätta.
Tack för hjälpen!