[go: up one dir, main page]

0% found this document useful (0 votes)
3 views67 pages

04 PSysCalls (Function)

Uploaded by

fabio.guelfi64
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views67 pages

04 PSysCalls (Function)

Uploaded by

fabio.guelfi64
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 67

[J]EMARO – Robotics Engineering

POSIX
ESSENTIALS
Part I - SysCalls 1

RUR Zaccaria, 2023-2024


POSIX Sistem Calls


Introduction

Files and directories

Processes

Inter Process Communication:

Pipe

Signal

Socket
Introduction
Posix includes also some standard C library functions

100 30 100

Numbers are approximate

printf()
C standard Posix
library
open() fopen()

3
Portable programs

4
C language interface

INTERRUPT

5
Header files
Posix has a series of #include <header files>
Frequently used header files
<assert.h> <limits.h> errno.h
<locale.h> <stdlib.h> qrp.h
<complex.h>
<string.h> math.h
<ctype.h> <math.h>
netdb.h
<pthread.h> <sys/stat.h> pthread.h
<dirent.h>
<setjmp.h> <tgmath.h> signal.h
<dlfcn.h>
stdio.h
<time.h>
<errno.h> <signal.h> stdlib.h
<stdarg.h> <unistd.h> strings.h
<fcntl.h>
time.h
<stdbool.h> <utime.h>
<fenv.h> unistd.h
<float.h> <stddef.h> <wchar.h> types.h
<wctype.h> stat.h
<inttypes.h> <stdint.h>
….
<iso646.h> <stdio.h>

6
In general and error management


Most system calls return -1 in case of error

In this case they assign a specific error code to
the global variable
extern int errno;

If the system call succedes, errno is not reset.

Some system calls accept a variable number of arguments (only the first
ones may be mandatory – see man pages)

7
Errno.h

Header file errno.h holds the symbolic standard names of error
codes

More than 100 error codes, only few are system dependent:
run-time diagnostics can be very accurate!
● Consult man errorno for list and details

Examples of frequently occurring:
EPERM 1 Operation not permitted (e.g. not owner)
ENOENT 2 No such file or directory
ESRCH 3 No such process ECHILD 10 No child processes
EINTR 4 Interrupted system call EACCES 13 Permission denied
EIO 5 Input/output error EBUSY 16 Device or resource busy
EEXIST 17 File exists
EPIPE 32 Broken pipe

8
perror
void perror (const char *str )

Converts the code in errno into an english message and prints

it prefixed by str
str: error message

str is used to identify the code point in which the error occurred:

…..
fd=open("nonexist.txt", O_RDONLY);
if (fd==-1) perror ("main");
…..
--> main: No such file or directory

9
man

A man page (short for manual page) is a form of software
documentation usually found on a Unix or Unix-like operating system.
Topics covered include computer programs (including library and
system calls), formal standards and conventions, and even abstract
concepts. A user may invoke a man page by issuing the man
command.

By default, man typically uses a terminal pager program such as
more or less to display its output.

To read a manual page for a Unix command, a user can type:
man < [section] command_name>


The section is optional.

10
man sections


Section Description

1 General commands

2 System calls

3 Library functions, covering in particular the C standard library

4 Special files (usually devices, those found in /dev) and drivers

5 File formats and conventions

6 Games and screensavers

7 Miscellanea

8 System administration commands and daemons

11
man example

12
Files primitives
• Creating files, directories, special files
• Open / Close files
• File access
• File and record locking
• Creating and destroying a link
• Reading file attributes
• Changing file attributes
• Changing the current directory
• Redirection and pipeline

13
the concept of file in Posix
A Posix file is much more than a collection of data on a disk.

Posix inherits the file concept from Unix.

A file is an abstract entity which supports most part of data


transfer regarding:

Process to process

Process and kernel

Process and devices

Process and the network

Files are better described in Part II.

14
opening a file
To use a file you must first open it with

the open() syscall:

• finds the file in the file system through its pathname


• copies in memory its i-node
• gives the file an integer >=0 (file descriptor)
that will identify the file in any operation
Three standard files for basic input and output
are opened by the shell that you are using when you
run a program. They are file descriptors 0 (standard
Input), 1 (standard output) and 2 (standard error).

close() disconnects the file descriptor from the file.

15
opening / closing
int fd;
...
fd=open(pathname, ...);

...
read(fd, ...);
...
write(fd,...);
...
close(fd);

Note:
A file can be opened more than once, so that
multiple file descriptors can point to the same file

16
open
int open (const char *pathname, int flag [,…]);
• opens (or creates)the file pathname,
with policy defined by flag
• returns a file descriptor fur futher use (or -1 if error)
flag: O_RDONLY read-only

O_WRONLY write-only

O_RDWR read and write


O_CREAT create if non existing
…….
Flags are bitwise constants that can be or-composed (“|”)
Additional mode specifications (r, w, x) can be added for user and group
(see creat)
17
creat
int creat (const char *path, mode_t mode);

• creates a new regular file with


path, opened for writing
• mode specifies permissions; owner is
the effective user-id of the process
• an existing file is emptied (owner and mode
do not vary)
• returns the file descriptor, or -1 if error

read manual for details
● a file can be created also by open, but:
creat always creates a new empty file
open preserves an existing file

18
close

int close (int fildes);

• closes the file descriptor fildes


• returns the operation’s exit status (0 or -1)

Note:
When a process exits, all its files are
closed by an implicit close.

19
read

ssize_t read (int fildes, void *buf, size_t nbyte);

• reads in *buf a sequence of nbyte bytes


from current position in file fildes
• updates the current position
• returns the number of bytes effectively read, or
-1 if error

20
write

ssize_t write(int fildes,


const void *buf,size_t nbyte);

• writes nbyte bytes into file fildes from *buf


starting from the current position in the file
• updates the current position
• returns the number of bytes effectively written,
or -1 If error

21
example
Copy standard input into standard output
#include ...
#define BUFFSIZE 8192
int main(void)
{
int n;
char buf[BUFFSIZE];
while( (n=read(STDIN_FILENO, buf, BUFFSIZE)) > 0)
if (write(STDOUT_FILENO, buf, n) != n)
perror("main");
if (n<0)
perror("main");
exit(0);
}

22
example

Note:
• the correct file descriptors are:
STDIN_FILENO and STDOUT_FILENO
they are defined in <unistd.h>
O and 1 can be used instead
• standard input and standard output do not need open/close

23
example

The example’s performance depends on the buffer size.


From: W.R.Stevens, Advanced Programming in the Unix Environment

Test with 1.468.802 bytes read, variable BUFFSIZE,file


system with 8192 bytes clusters (Berkeley fast file system)

24
example
BUFFSIZE User CPU System CPU Clock time # loops
(seconds) (seconds) (seconds)
1 23.8 397.9 423.4 1468802
2 12.3 202.0 215.2 734401
4 6.1 100.6 107.2 367201
8 3.0 50.7 54.0 183601
16 1.5 25.3 27.0 91801
32 0.7 12.8 13.7 45901
64 0.3 6.6 7.0 22950
128 0.2 3.3 3.6 11475
256 0.1 1.8 1.9 5738
512 0.0 1.0 1.1 2869
1024 0.0 0.6 0.6 1435
2048 0.0 0.4 0.4 718
4096 0.0 0.4 0.4 359
8192 0.0 0.3 0.3 180
16384 0.0 0.3 0.3 90
32768 0.0 0.3 0.3 45
65536 0.0 0.3 0.3 23
131072 0.0 0.3 0.3 12

25
example

Note:
The kernel strongly uses caching to limit physical I/O

MEMORY DISC
write (..., buf, ...)

read (..., buf, ...)

cache

cluster

Caching is stopped and flushed by the “flush” system


calls

26
flushing


A series of POSIX system calls provide I/O flushing, as to say
synchronizing a file's in-core state with storage device

Different functions are available (most popular: sync, fflush,
fsync and others).

The simplest one is

int fsync ( int fd );

Where fd is a file descriptor referring to the I/O stream we


want to flush, emptying any cache inside the operating
system. It is typically used when writing.

27
lseek
off_t lseek(int fildes,off_t offset, int whence);


advances the current position for reading/writing in
the file fildes of offset bytes starting from the
position specifiedin whence

SEEK_SET from beginning of the file


SEEK_CUR from current position
SEEK_END from end of file

Note:
lseek does not carry out I/O operations

28
link

int link(const char *existing, const char *new);

● Creates a new hard link new to the file existing



Returns 0 or -1 if error

29
rename
int rename (const char *old, const char *new);

● Renames the file from old to new



Returns 0 or -1 if error

30
unlink

int unlink (const char *path);

• each file can have several active links


• the first link is setup by creat
• deletes the hard link path and, if it is the last link,
deletes (deallocates) the file
• returns 0 or -1 )
Note:
• if the file is in use, only its directory entry is deallocated;
the file will be deallocated only when all its
file descriptors have been closed.
• an executable can make a link to itself
to prevent someone to cancel its file during execution

31
directories
int mkdir(const char *path,mode_t mode);

Creates an empty directory


int rmdir(const char *path);

Removes a directory

int chdir(const char *path);


Changes the working directory

32
directories

Portable directory structure, common syscalls:

struct dirent {
ino_t d_ino;/*i-number*/
char d_name[NAME_MAX+1]/*filename*/
};

DIR *opendir(const char *dirname);

struct dirent *readdir(DIR *dirp);

int closedir(DIR *dirp);

void rewinddir(DIR *dirp);

33
file status

int stat(const char *path,


struct stat *buf);

int fstat(int fildes,


struct stat *buf);
● Loads into buf some status information about the path
or the fildes file descriptor as defined in stat.h

34
file status
Header file stat.h:

st_dev device number


st_ino i-number
st_mode permission
st_nlink no. of (hard) links
st_uid user id
st_gid group id
st_size file dimension
st_atime last access time
st_mtime last modification time
st_ctime last status change time

35
file attributes
int chmod(const char *path, mode_t mode);
Changes permission of the file path as specified in mode

int chown (const char *path,


uid_t owner, gid_t group);
Changes owner and group of the file path

int utime (const char *path,


const struct utimbuf *times);
Changes timestamps of the file path as specified in times

36
dup

int dup (int fildes);

• creates a file descriptor alias


• associates the file of file descriptor fildes with an additional
file descriptor

the new file descriptor is the lowest number available from 0
• returns -1 if error

37
dup

38
file system administration
POSIX does not include system calls for file system administration

Examples of typical Unix system calls at this purpose:


mknod(pathname, type, device);
• creates a new file of type (regular,
directory, device or named pipe)
mount(device, directory, mode)
• mounts the file system stored in device in the
directory of the root file system, with mode permission
umount(device)
• unmounts the file system mounted in device

39
concurrent access to files

Files (entities referred to by a file descriptor) are shareable
resources

No mutual exclusion is provided

Two (or more) processes can concurrently read / write from / to
a same file

Race condition are possible (data jamming)

Some special files used for IPC intrinsically provide mutual
exclusion (see e.g. pipes in the following)

System calls for mutual exclusion (called locking) are available

40
file and record locking

An entire file can be locked as well as some part of it
(record)

A lock can prevent simultaneous read/write by different
processes

A lock is advisory if holds only for groups of processes
participating in the locking

A lock is mandatory if any process is excluded when one
process locks the file/record (discouraged in POSIX)

Locks must be set and freed like Dijkstra’s semaphores: a
lock is in principle a P operation, unlocking is V

41
file and record locking


locking / unlocking in POSIX is complex

several system calls are available
fcntl(), flock() lockf()

The simplest system call is:
int flock(int fd, int operation);

42
file and record locking

int flock(int fd, int operation);


fd open file descriptor
operation may be:
LOCK_SH a shared lock. More than one process may hold a
shared lock for a given file at a given time.
LOCK_EX an exclusive lock. Only one process may hold an
exclusive lock for a given file at a given time
LOCK_UN Remove an existing lock held by this process.

43
POSIX file system calls 1/2

POSIX Primitives Description


fildes=creat(path, mode) creates a new file
fildes=open(path, oflag, ...) opens un file
r=close(fildes) closes an open file
n=read(fildes,&buf,nbyte) reads data from file to buffer
n=write(fildes,&buf,nbyte) writes data from buffer into file
newoffset=lseek(fildes,offset, moves the file pointer
to some point in the file
whence)
r=link(existing, new) creates a new link to a file
r=unlink(path) removes a link
r=rename(oldpath,newpath) changes the name of a file
r=stat(path, &buf) returns information on the status
r=fstat(fildes, &buf) of a file

44
POSIX file system calls 2/2

POSIX Primitives Description


r=mkdir(path, mode) creates a new directory
r=rmdir(path) removes an empty directory
r=chdir(path) changes the working directory
newfildes=dup(fildes) duplicates the file descriptor fildes
s=pipe(fd_pipe) creates an unnamed pipe
s=chdir(dirname) changes the working directory
r=chmod(path, mode) changes the file’s permissions
r=chown(path,owner,group) changes owner and group of
a file
r=utime(path, &time) changes time information of a
file

45
file descriptor vs. streams

C language has a standard library for file management based
on the type FILE
● FILE is a type of a “file pointer” (or stream) variable
FILE * fp;
which is not a file descriptor.

A stream can be opened, closed, read and written by specific
C standard library functions (they all are prefixed by “f”):
fopen(), fclose(), fread(), fwrite(),
fscanf(), fprintf()
file descriptor vs. streams

● fopen(), fclose(), fread(), fwrite()


are similar to open(), close(), read(), write()
they are used for binary (non formatted, raw) I/O
● fscanf(), fprintf()
are similar to scanf() and printf() they carry out
format conversion
file descriptor vs. streams


a file descriptor can be derived by a stream by the
function fileno
int fileno( FILE * fp );

a file pointer can be derived by a file descriptor by the
function fdopen
FILE * fdopen();
process management


A process image file is composed of 4 main
parts
u-area

data

stack

text

49
process creation


A generic POSIX process is created by a parent
process by the fork system call
father

father son
Same execution environment of
u-area father: u-area (program counter,
u-area
open files, working directory, ...),
data and stack:
data data
fork()
stack stack

text text

child
father

50
fork

pid_t fork (void);

• creates a child process "identical" to the parent, and


returns:

to the child: 0
to the parent: PID of the child
in case of error: -1

51
fork
pid = fork();
if (pid<0) {/*fork failed */ }
else if(pid>0) {/*father’s code */}
else {/*son’s code*/}

father son

u-area u-area

data data

stack stack

text text

52
exec
pid_t exec (pathname, arguments)

• substitutes the caller’s image with the executable


file pathname, and executes it transferring arguments

53
execve

int execve(const char *pathname, char


*const argv[],
char *const envp[]);

● Executes the pathname file, transferring arguments


through argv and environment through envp

54
exec family

There are several exec system calls with tiny
differences

int execl ( const char *pathname, const char *arg0,... ); … list

int execv ( const char *pathname, char *const argv[] ); … vector

int execle ( const char *pathname, const char *arg0, ...,


char *const envp[] ); … environment
int execve ( const char *pathname, char *const argv[],
char *const envp[] );

int execlp ( const char *filename, const char *arg0, ... ); … path

int execvp ( const char *filename, char *const argv[] );

55
wait, waitpid

pid_t wait (int *statloc);

• suspends the calling process until one of its sons terminates


• returns the PID of the terminated son, or -1 if no sons
• assigns statloc the son’s exit status

pid_t waitpid (pid_t pid,


int *statloc, int options);

• specifies the son’s PID to wait for

56
_exit, exit


_exit is the POSIX system call, exit is the standard C call

exit calls _exit so they are identical

void _exit (int status);

• terminates the calling process

• the status value is available for the father process


through the wait system call

57
times
clock_t times (struct tms *buf);

• returns in buf some counters


about CPU time used by the process and its sons
struct tms {
clock_t tms_utime; /*user CPU time*/
clock_t tms_stime; /*system CPU time*/
clock_t tms_cutime; /*user CPU time of terminated
children*/
clock_t tms_cstime; /*system CPU time of terminated
children*/
};

This is only an example of the several system


calls for measuring time – see man pages

58
the sleep family

in several situations a process may require rescheduling for a
certain time amount

the sleep family of system calls is available at this purpose

a sleep action moves the process to the waiting state for a
specified time interval; after that, the process goes to ready
state

the family is composed by three system calls with different time
scales: sleep (seconds), usleep (microseconds) and
nanosleep (nanoseconds)

very short intervals may use busy waiting instead of
rescheduling (no switcher action)

59
the sleep family

unsigned int sleep (unsigned int seconds);


● suspends the caller for seconds seconds

returns the effective estimated suspension (the caller may
have some pending action to execute, see signals section), or
-1 if error
int usleep(unsigned int usec);
● like sleep, with usec in microseconds

60
The sleep family
int nanosleep(const struct timespec *req,
struct timespec *rem);

struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};


Suspends the execution of the caller until either:
1) at least the time specified in *req has elapsed, or
2) a signal (see signal section) has interrupted the caller.

● If the call is interrupted, nanosleep returns -1, sets errno to EINTR, and writes the
remaining time into the structure pointed to by rem. The value of *rem can then be
used to call nanosleep again and complete the specified pause.

● nanosleep is the most complete and reliable system call of the family.

61
Example 1: how the shell works
write(1, PROMPT); //STD_OUT
while ((n=read(0,buffer,80)=!0) { //STD_IN
/* command line processing, parse filename */
if ((pid=fork()) == 0) {

/* I/O redirection - see later*/


if (exec(file,args)==-1) exit(1);
}
procid=wait(status);
if (status!=0) write(2,’cmd not found’); //STD_ERR
write(1, PROMPT); //STD_OUT
}

62
shell and redirection

The shell language includes redirection, background and pipeline commands
● Let “$” be the prompt message from the shell
● $ command > filename means: command redirects its STD_OUT onto
filename (writes on filename)
● $ command < filename means: command redirects its STD_IN onto
filename (reads from filename)
● $ command & means: command is executed in background (the shell returns
immediately to prompt without waiting command completion)
● $ command_1 | command_2 means: STD_OUT of command_1 is redirected
onto STD_IN of command_2 (a pipeline)
● >, <, |, & can be composed in several intuitive ways
● Any file descriptor n can be redirected with the sintax n> or n< (> and < as
above are shortcuts for 1> and 0<, respectively)
● STD_ERR can hence be redirected with 2< and 2>
63
shell and redirection
Examples using generic processes
Assume that all processes read by default from STD_IN, write on
STD_OUT and write errors on STD_ERR

● $ proc1> file

proc1 redirects its normal output to file
● $ proc1 | proc2

the output of proc1 is send as input of proc2 (pipeline)
● $ proc1 < file

proc1 reads its input from a file
● $ proc1 < file1 > file2

proc1 reads from file1 and writes on file2
● $ proc1 2>/ logfile.txt | proc2 > file &
● $

proc1 sends its output to proc2; proc2 writes into file2; error messages
from proc1 are written into a logfile; the whole command is executed in
background returning to the shell upon execution start

64
shell and redirection
The same examples using system processes
● $ man fork > textfile

writes a man page into textfile
● $ ls usr/bin | grep icon

lists the directory /usr/bin and sends the outptut to the program sort (which
usually reads from STD_IN); and it shows on the screen
● $ sort < textfile.txt

the program sort reads the text to sort from textfile.txt instead of STD_IN
● $ sort < textfile.txt > textfile_sorted.txt

same as above, but sort writes into a file
● $ ls -R / 2>/dev/null | grep “*.txt” > result.txt &

lists recursively the entire file system, sends error messages to a dummy
output, sends the right output to grep which filters a certain pattern, and writes
results into a textfile; since execution takes many seconds, the whole pipeline
is executed in background so that the shells gains immediate control

65
Example 1: how the shell works
We can complete the previous example 1 with redirection and
background execution (pipeline will follow in part II)

write(1, PROMPT); //STD_OUT

while ((n=read(0,buffer,80)=!0) { //STD_IN

/* command line processing, parse filename */

if ((pid=fork()) == 0) {

/* I/O redirection - see later*/

if (exec(file,args)==-1) exit(1);

procid=wait(status);

if (status!=0) write(2,’cmd not found’); //STD_ERR

write(1, PROMPT); //STD_OUT

66
Example 2: how the shell works
write(1, PROMPT);
while ((n=read(0,buffer,80)=!0) {
/* command line processing: parse filename,redirection on
file f, and background_execution */
if ((pid=fork()) == 0) { redirects file
if (output_redirection) descriptor 1 onto file
fd=creat("f", ...); descriptor of file f
close(1);
dup(fd);
close(fd);
}
if (exec(file,args)==-1) exit(1); if “&” command,
} does not wait
if (!background_execution) {
procid=wait(status);
if (status!=0) write(2,’cmd not found’);
}
write(1, PROMPT);
}

67

You might also like