Title: COMP309/509 - Lecture 5 class: middle, center, inverse
fcntl#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *path, mode_t mode);
int mkfifoat(int dirfd, const char *pathname, mode_t mode);
path is the path for the FIFO (if this is an absolute pathname fd is ignored in mkfifoat(..)mode is the open mode (i.e. read/write).fd is a file descriptor that represents a directory. the FIFO is created relative to the directory.#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
int fd;
char * myfifo = "/tmp/myfifo";
/* create the FIFO (named pipe) */
mkfifo(myfifo, 0666);
/* write "Hi" to the FIFO */
fd = open(myfifo, O_WRONLY);
write(fd, "Hi", sizeof("COMP309 is cool!"));
close(fd);
/* remove the FIFO */
unlink(myfifo);
return 0;
}
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#define MAX_BUF 1024
int main(){
int fd;
char * myfifo = "/tmp/myfifo";
char buf[MAX_BUF];
/* open, read, and display the message from the FIFO */
fd = open(myfifo, O_RDONLY);
read(fd, buf, MAX_BUF);
printf("Received: %s\n", buf);
close(fd);
return 0;
}
].center[
]
flock in <sys/file.h>lockf in <unistd.h>fcntl in <fcntl.h>fcntl. fcntl locks are also called record locks
l_type of F_RDLCK) and write (F_WRLCK) locks on file descriptors.fork().exec()./proc/locks.int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
int fcntl(int fd, /* open file descriptor */
int cmd, /* F_GETLK, F_SETLK or F_SETLKW */
struct flock *lock); /* a struct containing details etc */
Read man fcntl!
flock struct struct flock {
short l_type; /* Type of lock: F_RDLCK,F_WRLCK, F_UNLCK */
short l_whence; /* How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* Starting offset for lock */
off_t l_len; /* Number of bytes to lock */
pid_t l_pid; /* PID of process blocking our lock (F_GETLK only) */
};
fd do the following:l_type field of lock to F_RDLCK for a read lock.l_type field of lock to F_WRLCK for a write lock.errcode = fcntl(fd, F_SETLK, &lock);
/*filelock.h*/
#include <fcntl.h> /* for struct flock */
typedef struct flock fileLock_t;
typedef fileLock_t *fileLock_p;
/* make a nice clean lock */
fileLock_p makeLock(void);
/* obtains a write lock on the fd, returns the call to fcntl */
int getLock(fileLock_p lock, int fd);
/* unlocks the write lock on fd, returns the call to fcntl */
int unLock(fileLock_p lock, int fd);
/* frees the lock made by a makeLock */
void freeLock(fileLock_p lock);
#include <stdlib.h> /* for NULL */
#include <stdio.h> /* for fprintf */
#include <string.h> /* for memset */
#include "fileLock.h" /* includes <fcntl.h> */
fileLock_p makeLock(void){
fileLock_p retval = (fileLock_p)calloc(1, sizeof(fileLock_t));
if(retval == NULL){
perror("makeLock: calloc failed!");
}
return retval;
}
int getLock(fileLock_p lock, int fd){
memset(lock, 0, sizeof(fileLock_t));
lock->l_type = F_WRLCK;
return fcntl(fd, F_SETLKW, lock);
}
...
...
int unLock(fileLock_p lock, int fd){
lock->l_type = F_UNLCK;
return fcntl(fd, F_SETLKW, lock);
}
void freeLock(fileLock_p lock){
free(lock);
}
#include <stdio.h> /* for fprintf */
#include <stdlib.h> /* for exit */
#include <sys/types.h> /* for open */
#include <sys/stat.h> /* for open */
#include <fcntl.h> /* for open */
#include "fileLock.h"
int main(int argc, char** argv){
int fd;
char* file;
if(argc != 2){
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
exit(EXIT_FAILURE);
}
...
file = argv[1];
fd = open(file, O_RDWR, S_IRWXU);
if(fd < 0){
perror("File opening failed.");
exit(EXIT_FAILURE);
} else {
int lval;
fileLock_p lock = makeLock();
if(lock == NULL){
perror("Lock creation failed.");
exit(EXIT_FAILURE);
}
...
fprintf(stderr, "Attempting to lock %s\n", file);
lval = getLock(lock, fd);
if(lval == -1){
perror("Locking failed");
exit(EXIT_FAILURE);
}
fprintf(stderr, "Successfully locked %s (hit any key to continue)\n", file);
getchar();
unLock(lock, fd);
freeLock(lock);
exit(EXIT_SUCCESS);
}
}
shmget:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
#include <sys/mman.h>
void *mmap(void *start, size_t length, int prot ,
int flags, int fd, off_t offset);
mmap in this unit as its slightly more portable.mmap allows us to map a file into a processes' memory. void *mmap(void *start, size_t length, int prot ,int flags, int fd, off_t offset);
prot & flags shortly.mmap returns the address of the mapped memoryMAP_FAILED is returned, MAP_FAILED is -1.mmap is preserved across forks, with the same attributes.prot is the desired memory protection of the mapped memory.prot is PROT_NONE or the bitwise OR of one or more of
PROT_READ – The memory may be read.PROT_WRITE – The memory may be written.PROT_EXEC – The memory may be executed.PROT_NONE means the memory is inaccessible.MAP_FIXEDMAP_PRIVATEMAP_SHAREDMAP_PRIVATE and MAP_SHARED are incompatible.MAP_PRIVATE means the mapping is not visible to other processes.MAP_FIXED means you are fussy about the starting address start.MAP_SHARED is the mode we will use.startaddr = mmap(0,
size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
0);
fd is a file we have made especially.size is how much space we need and will be the size of the file.
The return address will be what we are interested in!In the first example we will treat the memory startaddr as a pointer to an int:
int *count;
...
size_t size = sizeof(int);
...
startaddr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(start_addr == MAP_FAILED){
perror("mmap failed");
exit(EXIT_FAILURE);
}
...
count = (int *)start_addr;
startaddr as a pointer to an struct:typedef struct shared {
int nprocs;
pid_t pids[PROC_MAX];
} shared_t;
size_t size = sizeof(shared_t);
shared_t *shared;
startaddr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(start_addr == MAP_FAILED){
perror("mmap failed");
exit(EXIT_FAILURE);
}
shared = (shared_t *)start_addr;
fcntlclass: middle, center, inverse