Zadania
-
parallel.c
- uproszczona implementacja GNU parallel. Dla każdej linii standardowego wejścia program uruchamia osobny podproces, który wykonuje dane polecenie. Po uruchomieniu wszystkich podprocesów czeka na ich zakończenie../parallel
wywołuje polecenie przekazane przez argumenty, zastępując:-
ciąg
{}
linią przekazaną na standardowe wejście, -
ciąg
{.}
linią przekazaną na standardowe wejście bez rozszerzenia (jeśli takie występowało) -
ciąg
{/}
nazwą pliku (basename
) przekazaną na standardowe wejście -
ciąg
{//}
ścieżką bez nazwy pliku (dirname
) przekazaną na standardowe wejście
-
Testowanie parallel.c
:
$ # Stworzenie pliku o rozmiarze 1GiB:
$ dd if=/dev/urandom of=1g.dat bs=1G count=1
$ time wc -w 1g.dat 1g.dat
24590384 1g.dat
24590384 1g.dat
49180768 total
real 1m27,955s
user 1m27,192s
sys 0m0,359s
$ time printf "1g.dat\n1g.dat\n" | parallel wc -w "{}"
24590384 1g.dat
24590384 1g.dat
real 0m51,513s
user 1m38,512s
sys 0m0,432s
$ # Należy wcześniej przygotować pliki c, które chcemy skompilować. Najpierw możemy wypisać komendę:
$ ls *.c | parallel echo cc -c -o "{.}.o" "{}"
cc -c -o lapi.o lapi.c
cc -c -o lauxlib.o lauxlib.c
cc -c -o lbaselib.o lbaselib.c
cc -c -o lcode.o lcode.c
cc -c -o lcorolib.o lcorolib.c
cc -c -o lctype.o lctype.c
cc -c -o ldblib.o ldblib.c
cc -c -o ldebug.o ldebug.c
cc -c -o ldo.o ldo.c
cc -c -o ldump.o ldump.c
cc -c -o lfunc.o lfunc.c
cc -c -o lgc.o lgc.c
cc -c -o linit.o linit.c
cc -c -o liolib.o liolib.c
cc -c -o llex.o llex.c
cc -c -o lmathlib.o lmathlib.c
cc -c -o lmem.o lmem.c
cc -c -o loadlib.o loadlib.c
cc -c -o lobject.o lobject.c
cc -c -o lopcodes.o lopcodes.c
cc -c -o loslib.o loslib.c
cc -c -o lparser.o lparser.c
cc -c -o lstate.o lstate.c
cc -c -o lstring.o lstring.c
cc -c -o lstrlib.o lstrlib.c
cc -c -o ltable.o ltable.c
cc -c -o ltablib.o ltablib.c
cc -c -o ltm.o ltm.c
cc -c -o lua.o lua.c
cc -c -o luac.o luac.c
cc -c -o lundump.o lundump.c
cc -c -o lutf8lib.o lutf8lib.c
cc -c -o lvm.o lvm.c
cc -c -o lzio.o lzio.c
$ # a potem wykonać
$ ls *.c | parallel cc -c -o "{.}.o" "{}"
$ cat paths.txt
/some/path
/some/other/path.txt
foo
bar.c
bar.tar.gz
$ parallel echo "line={} without-ext={.} basename={/} dirname={//}" <paths.txt
line=/some/path without-ext=/some/path basename=path dirname=/some
line=/some/other/path.txt without-ext=/some/other/path basename=path.txt dirname=/some/other
line=foo without-ext=foo basename=foo dirname=.
line=bar.c without-ext=bar basename=bar.c dirname=.
line=bar.tar.gz without-ext=bar.tar basename=bar.tar.gz dirname=.
Procesy (Linux)
Podprocesy
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int fib(int n)
{
return n < 2 ? n : fib(n-1) + fib(n-2);
}
int main()
{
for (int i = 30; i < 42; ++i) {
if (fork() == 0) {
printf("fib(%d) = %d\n", i, fib(i));
return 0;
}
}
while (wait(NULL) > 0 || errno != ECHILD) {}
return 0;
}
Wykonywanie programu
-
Rodzina funkcji
exec
#include <unistd.h>
int main()
{
execl("/bin/echo", "echo", "hello, world", NULL);
}
#include <unistd.h>
int main()
{
execlp("echo", "echo", "hello, world", NULL);
}
#include <unistd.h>
#include <string.h>
int main()
{
char* argv[] = {
strdup("echo"),
strdup("hello, world"),
NULL
};
execv("/bin/echo", argv);
}
#include <unistd.h>
#include <string.h>
int main()
{
char* argv[] = {
strdup("echo"),
strdup("hello, world"),
NULL
};
execvp("echo", argv);
}
Ścieżki / nazwy plików
Rozwiązywanie ścieżek
Są 3 formy ścieżek:
-
relatywna - ścieżka opisująca położenie pliku w stosunku do aktualnego katalogu:
foo.c
,../foo.c
,./foo.c
-
bezwględna - ścieżka opisująca położenie pliku rozpoczynając od korzenia systmeu plików
/foo.c
,/foo/../foo.c
-
kanoniczna bezwględna - ścieżka nie wykorzystująca dowiązań symboliccznych, nadmiarowych znaków
/
oraz relatywnych nazw..
,.
(zwracana przezrealpath
)
Komponenty ścieżki
path dirname basename /usr/lib /usr lib /usr/ / usr usr . usr / / / . . . .. . ..
Funkcje dirname
i basename
mogą modyfikować przekazane do nich ścieżki lub wykorzystywać wewnętrzne bufory - przez co zwracane przez nie ścieżki nie powinny być przez nas przechowywane.
Kolejne wywołanie funkcji dirname
/basename
może nadpisać wewnętrzny bufor.