PB071: Úvod do jazyka C - 8

Návaznost C na OS, zejména Unix

Provádění příkazů OS a programů

Funkce system

#include <stdlib.h>
int system(příkaz)

Provede příkaz operačního systému; k tomu účelu spustí shell. Sortiment a syntax příkazů vyplývá z použitého operačního systému.Návratová hodnota udává, zda se podařilo spustit shell a příkaz - nemusí, ale může vracet návratovou hodnotu příkazu samotného. Lze provést i interní příkaz shellu. Součást normy, použitelné nejen v Unixu!

Funkce rodiny exec

#include <unistd.h> /* někdy <stdlib.h> nebo <process.h> */
int execl(path, arg, ...)
int execlp(file, arg, ...)
int execle(path, arg, ..., envp)
int execv(path, argv)
int execvp(file, argv)
int execve(path, argv, envp)

Borland má navíc execlpe, execvpe

path úplný název souboru (včetně cesty)
file koncový název souboru, hledá se podle proměnné PATH
arg argumenty předávané programu (jednotlivě)
argv pole argumentů
evnp pole proměnných prostředí

První argument, tj. arg nebo argv[0] opakuje název souboru s programem. Posledním argumentem musí být prázdný ukazatel.

Použitelné nejen v Unixu!

Z programu spuštěného pomocí některé z těchto funkcí není možný návrat zpět do volajícího programu, tj. po ukončení volaného programu následuje návrat do shellu, popř. návrat tam, odkud byl volající program spuštěn.

Spuštění jiného programu s návratem

Borland: funkce rodiny spawn

spawnl, spawnle, spawnlp, spawnlpe
spawnv, spawnve, spawnvp, spawnvpe

Parametry jako u odpovídajících exec, předchází jim parametr mode s možnými hodnotami P_WAIT (čekej na dokončená synovského procesu), P_NOWAIT (spusť rodičovský a synovský proces souběžně), P_OVERLAY (nahraď rodičovský proses synovským jako u funkcí z rodiny exec).

UNIX: funkce fork()

int fork()

Spustí identický druhý proces. Do původního procesu vrátí jako funkční hodnotu PID nově spuštěného (synovského) procesu, do synovského procesu vrátí 0. V synovském procesu se pak provede exec*, rodičovský proces obvykle čeká na dokončení syna, ale věci, které na něm nezávisí, může provádět paralelně.

Příklad použití:

pid=fork();
if(pid==0)execlp(vi,vi,current_file,NULL); /* child */
else waitpid(pid,NULL,0); /* parent */

Provedení příkazu OS s rourou do V/V proudu

FILE* popen(příkaz,režim)
int pclose(proud)

Standardní výstup (vstup) příkazu je napojen rourou na standardní vstup (výstup) programu - směr pohybu dat je dán režimem, zadaným v příkaze popen.

Práce se soubory a adresáři

Změna aktuálního nebo kořenového adresáře

#include <unistd.h>
int chdir(const char *path);
int fchdir(int fildes);
int chroot(const char *path); // vyžaduje práva root
Po provedení chroot symbol / označuje zvolený adresář a mimo něj a jemu podřízené není možné se dostat.

Příkazy vracejí 0 nebo -1; indikace chyby je v extern int errno

Změna vlastníka nebo skupiny

#include <unistd.h>
#include <sys/types.h>
int chown(const char *path, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);
/* rozdíl se projeví u symbolických linků; označuje-li název symbolický link,
   lchown změní vlastníka samotného linku, chown vlastníka odkazovaného souboru */
int fchown(int fildes, uid_t owner, gid_t group);

Změna přístupových práv

#include <sys/types.h>
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
int fchmod(int fildes, mode_t mode);

mode se vyjádří oktalově (např. 0751) nebo symbolickými konstantami
  (např. S_IRWXU|S_IRGRP|S_IXGRP|S_IXOTH)

Vytváření a rušení adresářů, rušení souborů

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
int mkdir(const char *pathname, mode_t mode);
/* mode je dále omezen pomocí proměnné umask nastavené danému uživateli */
int rmdir(const char *pathname);
int unlink(const char *pathname);

Funkce unlink ruší přiřazení adresářové položky souboru. (Tentýž soubor může být zařazen do jednoho nebo více adresářů, i pod různými názvy. Pokud je tomu tak, i po zrušení položky soubor přežívá pod ostatními identitami. Zrušením poslední položky  se smaže i soubor sám.)

Zjištění informací o souboru

#include <sys/types.h>
#include <sys/stat.h>
int stat(const char *path, struct stat *buf);
int lstat(const char *path, struct stat *buf);
int fstat(int fildes, struct stat *buf);

buf obsahuje položky s poměrně průhlednými názvy: st_mode st_ino st_dev st_rdev st_nlink
  st_uid st_gid st_size st_atim st_mtim st_ctim

Analýza adresáře

V <dirent.h> je k dispozici skupina dalších nástrojů pro práci s adresáři: opendir readdir closedir, na některých systémech i seekdir telldir rewinddir aj.

Za nástroje nižší úrovně se považuje int getdents(unsigned int fd, struct dirent *dirp, unsigned int count);
(V některých systémech se jmenuje getdirentries)

Služby času

Reálný čas

#include <sys/types.h>
#include <time.h>
time_t time(time_t *tloc); /* počet sekund od 1. 1. 1970 */ 
char *ctime (const time_t *clock);
/* 26 znaků textově, např. Mon Apr 23 12:34:56 2007\n\0 */ 
double difftime (time_t time1, time_t time0);
/* vrátí počet sekund od time0 do time1 */ 

Další funkce pracují se strukturou tm

struct tm { 
 int tm_sec;
/* sekundy v minutě [0, 61] */ 
 int tm_min; /* minuty v hodině [0, 59] */ 
 int tm_hour; /* hodiny od půlnoci [0, 23] */ 
 int tm_mday; /* den v měsící [1, 31] */ 
 int tm_mon; /* měsíc [0, 11] (leden == 0!!!) */ 
 int tm_year; /* rok - 1900 */ 
 int tm_wday; /* den v týdnu [0, 6] (0 == neděle) */ 
 int tm_yday; /* den v roce [0, 365] (1. leden == 0) */ 
 int tm_isdst; /* indikátor letního času */
};  

time_t mktime (struct tm *timeptr); /* vrátí počet sekund od půlnoci 1. ledna 1970 pro okamžik,na nějž ukazuje parametr */
char *asctime (const struct tm *tm); /* analogicky, ale vrátí 26znakový řetězec */
struct tm *localtime (const time_t *clock); /* převede čas udaný v sekundách od půlnoci 1. ledna 1970 na tm*/
struct tm *gmtime (const time_t *clock);

Čas procesoru

clock_t times(struct tms *buffer);
/* tms obsahuje 4 čísla: čas spotřebovaný daným procesem, 
systémem na žádost procesu a dtto včetně synovských procesů */

Tyto časy se měří v jednotkách zvaných hodinové tiky (Clock tics). Počet tiků za sekundu uvádí makro CLK_TCK v hlavičkovém souboru limits.h (obvykle v Unixu 100, v MS DOSu zhruba 17).

Dále jsou k dispozici funkce setitimer a getitimer, které mohou měřit reálný čas i čas procesoru a generovat přerušení po uplynutí zadané doby.

Služby spojené s procesy

Zjištění PID

PID čili Process IDentifier je celé číslo přiřazené každému procesu

#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getpgrp(void);
pid_t getppid(void);
pid_t getpgid(pid_t pid);

Signály

#include <signal.h>
#include <sys/types.h>
int kill (pid_t pid, int sig); //vyšle procesu signál
void (*signal (int sig, void (*func)(int)))(int); //definuje reakci na daný druh signálu
int nice(int incr); //sníží procesu prioritu
Nejčastější signály: 
1: meziprocesová komunikace, určen k zachycení funkcí signal   
9: spořádané ukončení procesu (výzva "ukonči se")
15: nouzové ukončení, mohou zůstat spuštěné synovské procesy. Použít jen, nelze-li ukončit spořádaně.
Předchozí Předchozí přednáška Další Další přednáška Hlavní stránka Hlavní stránka