tp2
This commit is contained in:
parent
cfd590c9d2
commit
c9329259c6
151
tp/tp2/README.md
Normal file
151
tp/tp2/README.md
Normal file
@ -0,0 +1,151 @@
|
||||
# TP2 : Fichiers
|
||||
|
||||
#### Ex1
|
||||
Écrire deux versions d'un programme qui copie "octet par octet" un fichier source dans un fichier destination :
|
||||
|
||||
```
|
||||
./copy infile outfile
|
||||
```
|
||||
|
||||
en utilisant :
|
||||
|
||||
1. les appels systèmes linux : `open`, `read`, `write`, `close`.
|
||||
2. les fonctions E/S standards (sdtio) : `fopen`, `fread`, `fwrite`, `fclose`.
|
||||
|
||||
Testez vos deux programmes sur un fichier volumineux (utilisez la commande `dd` le pseudo fichier `dev/urandom` pour
|
||||
générer un contenu aléatoire) et expliquez pourquoi le deuxième programme est beaucoup plus rapide que le
|
||||
premier.
|
||||
|
||||
Remarques :
|
||||
- pour être dans les mêmes conditions, il faut être sur que le fichier à copier n'est pas en cache en mémoire. Générez un nouveau fichier de même taille, ou utilisez le programme [fadvise.c](./src/fadvise.c) qui permet de vider les blocs du cache pour un fichier quelconque.
|
||||
- utilisez `strace` pour tracer les appels systèmes de vos deux programmes.
|
||||
|
||||
#### Ex2
|
||||
Écrire un programme qui copie un fichier en utilisant `mmap`.
|
||||
|
||||
#### Ex3
|
||||
Compilez et exécutez Le programme [coherence.c](./src/coherence.c). Qu'est ce que cela montre ?
|
||||
|
||||
#### Ex4
|
||||
Le but est d'écrire en C un programme qui efface un fichier du disque de telle manière que le contenu effacé ne soit pas
|
||||
récupérable. Pour des raisons physiques, on procédera de la manière suivante :
|
||||
- Si l'inode correspondant au fichier à effacer a plusieurs références, on efface juste l'entrée du répertoire correspondant.
|
||||
- Sinon, on réécrit les blocs de données :
|
||||
- une première passe avec `0xff` pour tous les octets.
|
||||
- une deuxième passe avec des valeurs aléatoires (on utilisera le pseudo-fichier `/dev/urandom`)
|
||||
- enfin, avant d'effacer le fichier, on le renomera de manière aléatoire.
|
||||
|
||||
Toutes les E/S devront utilisées un cache.
|
||||
|
||||
|
||||
Fonctions utiles :
|
||||
|
||||
```c
|
||||
#include <sys/stat.h>
|
||||
int stat(const char *restrict pathname,
|
||||
struct stat *restrict statbuf);
|
||||
|
||||
#include <fcntl.h>
|
||||
int open(const char *pathname, int flags, ...
|
||||
/* mode_t mode */ );
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
ssize_t read(int fd, void buf[.count], size_t count);
|
||||
ssize_t write(int fd, const void buf[.count], size_t count);
|
||||
int unlink(const char *pathname);
|
||||
int close(int fd);
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
int rename(const char *oldpath, const char *newpath);
|
||||
```
|
||||
|
||||
#### Ex5
|
||||
Le but est d'écrire une version simplifiée de la commande `ls -al`.
|
||||
|
||||
```bash
|
||||
$./myls /
|
||||
drwxr-xr-x 18 root root 4096 07 sept. 12:48 ..
|
||||
drwxr-xr-x 6 root root 4096 03 nov. 09:40 srv
|
||||
drwxr-xr-x 10 root root 4096 24 sept. 21:07 usr
|
||||
dr-xr-xr-x 301 root root 0 18 sept. 07:10 proc
|
||||
drwxr-xr-x 312 root root 258048 12 sept. 09:46 lib
|
||||
drwxrwxrwt 25 root root 2140 27 sept. 13:02 tmp
|
||||
drwxr-xr-x 18 root root 4096 07 sept. 12:48 .
|
||||
drwxr-xr-x 5 root root 1024 07 sept. 12:57 boot
|
||||
drwxr-xr-x 32 root root 760 27 sept. 09:57 run
|
||||
drwxr-xr-x 11 root root 4096 25 juil. 18:14 opt
|
||||
drwxr-x--- 32 root root 4096 25 sept. 13:49 root
|
||||
drwxr-xr-x 122 root root 12288 27 sept. 09:57 etc
|
||||
drwxr-xr-x 4 root root 4096 10 déc. 08:27 home
|
||||
drwxr-xr-x 6 root root 151552 24 sept. 21:07 bin
|
||||
drwxr-xr-x 6 root root 151552 24 sept. 21:07 sbin
|
||||
drwxr-xr-x 23 root root 3580 27 sept. 09:57 dev
|
||||
drwxr-xr-x 10 root root 4096 13 sept. 13:33 media
|
||||
drwxr-xr-x 15 root root 4096 18 sept. 07:10 var
|
||||
drwxr-xr-x 312 root root 258048 12 sept. 09:46 lib64
|
||||
dr-xr-xr-x 13 root root 0 18 sept. 07:10 sys
|
||||
drwx------ 2 root root 16384 02 sept. 11:30 lost+found
|
||||
-rw-r--r-- 1 root root 2333 28 juin 20:49 fonts.conf
|
||||
drwxr-xr-x 2 root root 4096 02 sept. 11:40 mnt
|
||||
```
|
||||
|
||||
- pour parcourir les entrées du repertoire passé en argument :
|
||||
```c
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
DIR *opendir(const char *name);
|
||||
```
|
||||
|
||||
```c
|
||||
#include <dirent.h>
|
||||
|
||||
struct dirent *readdir(DIR *dirp);
|
||||
struct dirent {
|
||||
ino_t d_ino; /* Inode number */
|
||||
off_t d_off; /* Not an offset; see below */
|
||||
unsigned short d_reclen; /* Length of this record */
|
||||
unsigned char d_type; /* Type of file; not supported
|
||||
by all filesystem types */
|
||||
char d_name[256]; /* Null-terminated filename */
|
||||
};
|
||||
```
|
||||
|
||||
- les autres informations sont accessibles grâce à la fonction :
|
||||
|
||||
```c
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int stat(const char *pathname, struct stat *statbuf);
|
||||
|
||||
struct stat {
|
||||
dev_t st_dev; /* ID of device containing file */
|
||||
ino_t st_ino; /* Inode number */
|
||||
mode_t st_mode; /* File type and mode */
|
||||
nlink_t st_nlink; /* Number of hard links */
|
||||
uid_t st_uid; /* User ID of owner */
|
||||
gid_t st_gid; /* Group ID of owner */
|
||||
dev_t st_rdev; /* Device ID (if special file) */
|
||||
off_t st_size; /* Total size, in bytes */
|
||||
blksize_t st_blksize; /* Block size for filesystem I/O */
|
||||
blkcnt_t st_blocks; /* Number of 512B blocks allocated */
|
||||
|
||||
/* Since Linux 2.6, the kernel supports nanosecond
|
||||
precision for the following timestamp fields.
|
||||
For the details before Linux 2.6, see NOTES. */
|
||||
|
||||
struct timespec st_atim; /* Time of last access */
|
||||
struct timespec st_mtim; /* Time of last modification */
|
||||
struct timespec st_ctim; /* Time of last status change */
|
||||
|
||||
#define st_atime st_atim.tv_sec /* Backward compatibility */
|
||||
#define st_mtime st_mtim.tv_sec
|
||||
#define st_ctime st_ctim.tv_sec
|
||||
};
|
||||
```
|
||||
|
||||
Faire `man 7 inode`.
|
BIN
tp/tp2/src.tar.gz
Normal file
BIN
tp/tp2/src.tar.gz
Normal file
Binary file not shown.
96
tp/tp2/src/coherence.c
Normal file
96
tp/tp2/src/coherence.c
Normal file
@ -0,0 +1,96 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <sys/fcntl.h>
|
||||
|
||||
#define TESTFILE "coherence-test.txt"
|
||||
|
||||
void write_asr_c_pas_bien()
|
||||
{
|
||||
FILE* f = fopen(TESTFILE, "w");
|
||||
fprintf(f, "L'asr, c'est pas bien!\n");
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void write_asr_c_bien()
|
||||
{
|
||||
FILE* f = fopen(TESTFILE, "w");
|
||||
fprintf(f, "L'asr, c'est bien!!\n");
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
|
||||
void read_using_syscalls()
|
||||
{
|
||||
write_asr_c_pas_bien();
|
||||
|
||||
// open file descriptor
|
||||
int fd = open(TESTFILE, O_RDONLY);
|
||||
|
||||
// read first 12 bytes
|
||||
char buf[BUFSIZ];
|
||||
ssize_t nr1 = read(fd, buf, 12);
|
||||
assert(nr1 >= 0);
|
||||
|
||||
write_asr_c_bien();
|
||||
|
||||
// read rest of file, print to stdout
|
||||
ssize_t nr2 = read(fd, buf + nr1, BUFSIZ - nr1);
|
||||
close(fd);
|
||||
fwrite(buf, 1, nr1 + nr2, stdout);
|
||||
}
|
||||
|
||||
|
||||
void read_using_stdio()
|
||||
{
|
||||
write_asr_c_pas_bien();
|
||||
|
||||
// open stdio file
|
||||
FILE* f = fopen(TESTFILE, "r");
|
||||
|
||||
// read first 12 bytes
|
||||
char buf[BUFSIZ];
|
||||
size_t nr1 = fread(buf, 1, 12, f);
|
||||
|
||||
write_asr_c_bien();
|
||||
|
||||
// read rest of file, print to stdout
|
||||
size_t nr2 = fread(buf + nr1, 1, BUFSIZ - nr1, f);
|
||||
fclose(f);
|
||||
fwrite(buf, 1, nr1 + nr2, stdout);
|
||||
}
|
||||
|
||||
|
||||
static void usage()
|
||||
{
|
||||
fprintf(stderr, "Usage: ./coherence -l (linux syscalls) or ./coherence -s (stdio)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int which = 0;
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "ls")) != -1) {
|
||||
switch (opt) {
|
||||
case 's':
|
||||
which = 's';
|
||||
break;
|
||||
case 'l':
|
||||
which = 'l';
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (which == 's') {
|
||||
read_using_stdio();
|
||||
} else if (which == 'l') {
|
||||
read_using_syscalls();
|
||||
} else {
|
||||
usage();
|
||||
}
|
||||
}
|
35
tp/tp2/src/copy.c
Normal file
35
tp/tp2/src/copy.c
Normal file
@ -0,0 +1,35 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define BLOCK_SIZE 1
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int fin,
|
||||
fout;
|
||||
char buf[BLOCK_SIZE];
|
||||
|
||||
assert( argc == 3 );
|
||||
|
||||
fin = open(argv[1],O_RDONLY);
|
||||
assert( fin >= 0 );
|
||||
|
||||
fout = open(argv[2],O_CREAT|O_WRONLY|O_TRUNC,0600);
|
||||
assert( fout >= 0 );
|
||||
|
||||
while(1){
|
||||
ssize_t nb_read;
|
||||
nb_read = read(fin,buf,BLOCK_SIZE);
|
||||
if (nb_read <= 0)
|
||||
break;
|
||||
write(fout,buf,nb_read);
|
||||
}
|
||||
|
||||
close(fin);
|
||||
close(fout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
155
tp/tp2/src/fadvise.c
Normal file
155
tp/tp2/src/fadvise.c
Normal file
@ -0,0 +1,155 @@
|
||||
#include <linux/falloc.h>
|
||||
#include <linux/fadvise.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <asm/unistd_64.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
//#include <linux-ftools.h>
|
||||
#define LINUX_FTOOLS_VERSION "1.0.0"
|
||||
/**
|
||||
|
||||
SYNTAX: filename mode [offset] [,length]
|
||||
Where mode can be:
|
||||
|
||||
POSIX_FADV_NORMAL No further special treatment.
|
||||
POSIX_FADV_RANDOM Expect random page references.
|
||||
POSIX_FADV_SEQUENTIAL Expect sequential page references.
|
||||
POSIX_FADV_WILLNEED Will need these pages.
|
||||
POSIX_FADV_DONTNEED Don't need these pages.
|
||||
POSIX_FADV_NOREUSE Data will be accessed once.
|
||||
|
||||
Allows an application to to tell the kernel how it expects to use a file handle,
|
||||
so that the kernel can choose appropriate read-ahead and caching techniques for
|
||||
access to the corresponding file. This is similar to the POSIX version of the
|
||||
madvise system call, but for file access instead of memory access. The
|
||||
sys_fadvise64() function is obsolete and corresponds to a broken glibc API,
|
||||
sys_fadvise64_64() is the fixed version. The following are the values for the
|
||||
advice parameter:
|
||||
|
||||
FADV_NORMAL
|
||||
|
||||
No special treatment.
|
||||
|
||||
FADV_RANDOM
|
||||
|
||||
Expect page references in random order.
|
||||
|
||||
FADV_SEQUENTIAL
|
||||
|
||||
Expect page references in sequential order.
|
||||
|
||||
FADV_WILLNEED
|
||||
|
||||
Expect access in the near future.
|
||||
|
||||
FADV_DONTNEED
|
||||
|
||||
Do not expect access in the near future. Subsequent access of pages in this
|
||||
range will succeed, but will result either in reloading of the memory contents
|
||||
from the underlying mapped file or zero-fill-in-demand pages for mappings
|
||||
without an underlying file.
|
||||
|
||||
FADV_NOREUSE
|
||||
|
||||
Access data only once.
|
||||
|
||||
*/
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
if ( argc < 3 ) {
|
||||
fprintf( stderr, "%s version %s\n", argv[0], LINUX_FTOOLS_VERSION );
|
||||
printf( "SYNTAX: fadvise filename mode [offset] [,length]\n" );
|
||||
|
||||
printf( "Where mode can be:\n\n" );
|
||||
|
||||
printf( " POSIX_FADV_NORMAL No further special treatment. \n" );
|
||||
printf( " POSIX_FADV_RANDOM Expect random page references. \n" );
|
||||
printf( " POSIX_FADV_SEQUENTIAL Expect sequential page references. \n" );
|
||||
printf( " POSIX_FADV_WILLNEED Will need these pages. \n" );
|
||||
printf( " POSIX_FADV_DONTNEED Don't need these pages. \n" );
|
||||
printf( " POSIX_FADV_NOREUSE Data will be accessed once. \n" );
|
||||
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
char* path = argv[1];
|
||||
char* param_mode = argv[2];
|
||||
|
||||
printf( "Going to fadvise %s\n", path );
|
||||
|
||||
int flags = O_RDWR;
|
||||
int fd = open( path, flags );
|
||||
|
||||
if ( fd == -1 ) {
|
||||
perror( NULL );
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct stat fd_stat ;
|
||||
|
||||
if ( fstat( fd, &fd_stat ) < 0 ) {
|
||||
perror( "Could not stat file: " );
|
||||
return 1;
|
||||
}
|
||||
|
||||
loff_t offset = 0;
|
||||
loff_t length = fd_stat.st_size;
|
||||
|
||||
if ( argc >= 4 ) {
|
||||
offset = strtol( argv[3], NULL, 10 );
|
||||
}
|
||||
|
||||
if ( argc >= 5 ) {
|
||||
length = strtol( argv[4], NULL, 10 );
|
||||
}
|
||||
|
||||
printf( "offset: %ld\n", offset );
|
||||
printf( "length: %ld\n", length );
|
||||
|
||||
int mode = -1;
|
||||
|
||||
if ( strcmp( param_mode , "POSIX_FADV_NORMAL" ) == 0 ) {
|
||||
mode = POSIX_FADV_NORMAL;
|
||||
} else if ( strcmp( param_mode , "POSIX_FADV_RANDOM" ) == 0 ) {
|
||||
mode = POSIX_FADV_RANDOM;
|
||||
} else if ( strcmp( param_mode , "POSIX_FADV_SEQUENTIAL" ) == 0 ) {
|
||||
mode = POSIX_FADV_SEQUENTIAL;
|
||||
} else if ( strcmp( param_mode , "POSIX_FADV_WILLNEED" ) == 0 ) {
|
||||
mode = POSIX_FADV_DONTNEED;
|
||||
} else if ( strcmp( param_mode , "POSIX_FADV_DONTNEED" ) == 0 ) {
|
||||
mode = POSIX_FADV_DONTNEED;
|
||||
} else if ( strcmp( param_mode , "POSIX_FADV_NOREUSE" ) == 0 ) {
|
||||
mode = POSIX_FADV_NOREUSE;
|
||||
} else {
|
||||
printf( "Invalid mode %s\n", param_mode );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
printf( "mode: %s\n", param_mode );
|
||||
|
||||
long result = syscall( SYS_fadvise64, fd, offset, length , mode );
|
||||
|
||||
if ( result != 0 ) {
|
||||
|
||||
if ( result != -1 ) {
|
||||
errno=result;
|
||||
perror( "Unable to fadvise" );
|
||||
} else {
|
||||
printf( "Unable to fadvise: %ld\n" , result );
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf( "WIN\n" );
|
||||
|
||||
close( fd );
|
||||
return 0;
|
||||
|
||||
}
|
70
tp/tp2/src/my_cp_map.c
Normal file
70
tp/tp2/src/my_cp_map.c
Normal file
@ -0,0 +1,70 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
|
||||
static inline double tstamp(void)
|
||||
{
|
||||
struct timespec tv;
|
||||
clock_gettime(CLOCK_REALTIME, &tv);
|
||||
return tv.tv_sec + tv.tv_nsec * 1.0e-9;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
//char buf[BUFSIZE];
|
||||
char * bufin = NULL,
|
||||
* bufout = NULL;
|
||||
|
||||
|
||||
int fin,
|
||||
fout;
|
||||
|
||||
double start,
|
||||
end;
|
||||
|
||||
size_t filesize = 0;
|
||||
|
||||
assert(argc == 3);
|
||||
|
||||
start = tstamp();
|
||||
|
||||
fin = open(argv[1],O_RDONLY);
|
||||
assert(fin >=0);
|
||||
|
||||
fout = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);
|
||||
assert(fout >=0);
|
||||
|
||||
filesize = lseek(fin,0,SEEK_END);
|
||||
ftruncate (fout,filesize);
|
||||
|
||||
bufin = mmap(NULL,filesize,PROT_READ,MAP_PRIVATE,fin,0);
|
||||
assert(bufin != (void*)-1);
|
||||
|
||||
bufout = mmap(NULL,filesize,PROT_WRITE,MAP_SHARED,fout,0);
|
||||
|
||||
assert(bufout != (void*)-1);
|
||||
|
||||
|
||||
memcpy(bufout,bufin,filesize);
|
||||
|
||||
//munmap(bufin,filesize);
|
||||
//munmap(bufout,filesize);
|
||||
|
||||
//ssize_t nb_read = read(fin,buf,sizeof(buf));
|
||||
close(fin);
|
||||
close(fout);
|
||||
|
||||
end = tstamp();
|
||||
|
||||
printf("time = %.3lf\n",end - start);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user