...
 
Commits (27)
#
# CSCI 315 Operating Systems Design
# Author: L. Felipe Perrone
# Date: 2011-04-21
# Copyright (c) 2011 Bucknell University
#
# Permission is hereby granted, free of charge, to any individual or
# institution obtaining a copy of this software and associated
# documentation files (the "Software"), to use, copy, modify, and
# distribute without restriction, provided that this copyright and
# permission notice is maintained, intact, in all copies and supporting
# documentation.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL BUCKNELL UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES
# OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# compiler
CC = gcc
CFLAGS = -g -Wall
EXE = file_stat read_dir fdump
all: $(EXE)
file_stat: file_stat.o
$(CC) $(CFLAGS) -o file_stat file_stat.o
file_stat.o: file_stat.c
$(CC) -c $(CFLAGS) file_stat.c
read_dir: read_dir.o
$(CC) -o read_dir read_dir.o
read_dir.o: read_dir.c
$(CC) -c $(CFLAGS) read_dir.c
hexdump.o: hexdump.h hexdump.c
$(CC) $(CFLAGS) -c hexdump.c -o hexdump.o
fdump: fdump.c hexdump.o
$(CC) $(CFLAGS) hexdump.o fdump.c -o fdump
clean:
/bin/rm -f *~ *.o core $(EXE)
3.1) Provide an example of operation in which changes only its time
of last status change
touch -d "date" filename
3.2) Provide an example of an operation on regular file which changes its
time of modification
You can use touch to a file as this is will change the time of modification
touch -m filename
3.3) Provide an example of an operation on a regular file which changes
its time of last access
touch -a filename
3.4) Provide an example of an application where knowing the maximum file name length io
is helpful. In this problem you can simply describe a scenario in which a given
program needs to have the maximum length file names.
You have a situation where a longer file name gets cut off if it exceeds the limit and
then two files could be stored under the same name causing an issue. If you knew the max size then
you would ensure that there are no situaions where file names are cut off due to lenght
and therefore corrupting files.
/*
* Copyright (c) 2012 Bucknell University
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: L. Felipe Perrone (perrone@bucknell.edu)
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "hexdump.h"
int main(int argc, char *argv[]) {
if (argc < 3){
printf("ERROR: INPUT AS: ./fdump filename(C array) offset(unsigned int) size(unsigned int)");
return -1;
}
FILE* file1;
int size1 = 100;
unsigned char *buffer = malloc(size1);
char* file = argv[1];
unsigned int off = atoi(argv[2]);
unsigned int size = atoi(argv[3]);
file1 = fopen(file, "r");
fseek(file1, off, SEEK_SET);
fgets((void*)buffer, size, file1);
hexdump(buffer, size);
fclose(file1);
return 0;
}
---------------------------------------------------------------------
Lab 10 -- Feedback
---------------------------------------------------------------------
Prelab:
fdump.c compiles and runs as expected 15/15
prelab.txt answers (4pts per q) 15/15
Problem 1:
output of file_stat.c is filled in 0/20
Problem 2:
traverse.c run as expected 0/10
traverse.c deals with links properly 0/5
Problem 3:
answer all the questions 8/8
Problem 4:
sender and reciever compile and run as expected 0/22
---------------------------------------------------------------------
TOTAL 38 / 100
---------------------------------------------------------------------
/*
* CSCI 315 Operating Systems Design
* Original developed by CSCI 315 staff
* Modified by: L. Felipe Perrone
* Date: 2011-4-21
* Copyright (c) 2011 Bucknell University
*
* Permission is hereby granted, free of charge, to any individual or
* institution obtaining a copy of this software and associated
* documentation files (the "Software"), to use, copy, modify, and
* distribute without restriction, provided that this copyright and
* permission notice is maintained, intact, in all copies and supporting
* documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL BUCKNELL UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <grp.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <pwd.h>
#include <time.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
// pointer to file name string
char *name;
// allocate tm structure to store retrieved time
struct tm time;
// allocate space to hold a string with retrieved time (ASCII text)
char asctime_str[35];
// container for complete set of file permission bits (binary)
unsigned int mode;
// container for the three bits of user permissions
unsigned int umode;
// container for the three bits of group permissions
unsigned int gmode;
// container for the three bits of owner permission
unsigned int omode;
// human readable file permissions (ASCII text)
char perm_bits_str[] = "---------";
// file descriptor
unsigned int fd;
// structure to contain the result of the fstat call (info on this file)
struct stat file_info;
// structure to contain the result of the vfstat call (info on file system)
struct statvfs fs_info;
// used to save the return value of realpath
char resolved_path[PATH_MAX];
char* ret_path;
// check number of arguments for appropriate usage
if (2 != argc) {
printf(" usage: %s [file_name]\n", argv[0]);
exit(-11);
}
// post-condition: argv[1] contains name of file to use
// try to open file
fd = open(argv[1], O_RDONLY);
if (-1 == fd) {
perror("Failed to open read only file - ");
exit(-1);
}
// use fstatvfs to learn details about the file system
if (fstatvfs(fd, &fs_info) == 0) {
printf("== FILE SYSTEM INFO ============================\n");
printf(" file system fstatvfs() call successful\n");
printf(" file system block size: %d\n", 0); // TO-DO
printf(" max. file name length: %d\n", 0); // TO-DO
} else {
printf("%s: File system fstatvfs call failed\n", argv[0]);
exit(-1);
}
// post-condition: maximum length of file name string is known
// use calloc to allocate space for file name string
name = calloc(fs_info.f_namemax, 1);
if (NULL == name) {
perror("Problem in calloc - ");
exit(-1);
}
// copy file name into name variable using secure version of string copy
strncpy(name, argv[1], 500);
// use fstat to get information on specific file
if (fstat(fd, &file_info) == 0) {
printf("\n== FILE INFO ============================\n");
printf(" file fstat() call successful\n");
// mode comes from the lower 9 bits in file_info.st_mode
mode = file_info.st_mode & 0x1FF;
printf(" file protection bits = 0%o\n", mode);
// umode comes from the high 3 bits in mode
umode = 0; // TO-DO
// gmode comes from the middle 3 bits in mode
gmode = 0; // TO-DO
// omode comes from the low 3 bits in mode
omode = 0; // TO-DO
// once you have set umode, gmode, and omode, the code below
// will construct the right string for you and display it
// construct string with file protection information
if (umode & 0x4) perm_bits_str[0] = 'r';
if (umode & 0x2) perm_bits_str[1] = 'w';
if (umode & 0x1) perm_bits_str[2] = 'x';
if (gmode & 0x4) perm_bits_str[3] = 'r';
if (gmode & 0x2) perm_bits_str[4] = 'w';
if (gmode & 0x1) perm_bits_str[5] = 'x';
if (omode & 0x4) perm_bits_str[6] = 'r';
if (omode & 0x2) perm_bits_str[7] = 'w';
if (omode & 0x1) perm_bits_str[8] = 'x';
printf(" file protection string = %s\n", perm_bits_str);
printf(" file protection mode (u:g:o) = %o:%o:%o\n",
umode, gmode, omode);
printf(" owner user name = %s\n",""); // TO-DO: man getpwuid
printf(" owner group name = %s\n", ""); // TO-DO: man getgrgid
// TO-DO: print "mode = x", where x may be:
// "regular file"
// "directory"
// "character device"
// "block device"
// "symbolic link"
// "socket"
// "fifo"
// "unknown"
if (S_ISREG(file_info.st_mode)) {
printf(" mode = regular file\n");
} else { // see TO-DO above
}
ret_path = realpath(name, resolved_path);
if (NULL != ret_path)
printf(" absolute path = %s\n", ret_path);
else {
perror(" couldn't resolve path");
exit(-1);
}
// fill in the time the last write was made to file
localtime_r(&(file_info.st_mtime), &time);
asctime_r(&time, asctime_str);
printf(" time of last modification: %s\n", asctime_str);
fflush(stdout);
close(fd);
exit(0);
}
else
printf(" fstat call failed\n");
return 0;
}
/*
* Copyright (c) 2012 Bucknell University
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: L. Felipe Perrone (perrone@bucknell.edu)
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "hexdump.h"
char is_printable(unsigned char c) {
if ((c >= 0x20) && (c < 0x7F))
return c;
else
return '.';
}
void hexdump(unsigned char* buffer, unsigned int length) {
int b=0, c=0;
int s, rem;
// b is a counter for the number of bytes (half the number of hex digits)
printf("\n PAYLOAD HEXDUMP:\n");
while (b < length) {
printf("\n %07x:", b);
for (; (b%16<15) && (b<length); b++) {
if (0 == b % 2)
printf(" ");
printf("%02hhx", buffer[b]);
}
if (b < length)
printf("%02hhx ", buffer[b++]);
else { // print a number of spaces to align the remaining text
rem = b % 16;
for (s=0; s < 44 - ((rem*2) + (rem/2) + 1); s++)
printf(" ");
}
for (;(c%16<15) && (c<length); c++) {
printf("%c", is_printable(buffer[c]));
}
if (c<length)
printf("%c", is_printable(buffer[c++]));
}
}
/*
* Copyright (c) 2012 Bucknell University
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: L. Felipe Perrone (perrone@bucknell.edu)
*/
#ifndef __HEXDUMP_H__
#define __HEXDUMP_H__
/**
* This function prints to stdout the contents of a buffer in hexadecimal
* and in its ASCII representation. The output is similar to what you would
* get by running the Linux utility xxd on a file.
*
* @param buffer pointer to a memory buffer
* @param length number of bytes in the buffer
*/
char is_printable(unsigned char c);
extern void hexdump(unsigned char* buffer, unsigned int length);
#endif /* __HEXDUMP_H__ */
2.1) When I run dump with the file as hexdump, the offset as 1000 and the size as 128, I see
a lot of zero values in the given chart and then a variety of hex values.
PAYLOAD HEXDUMP:
0000000: 6c65 6e67 7468 2920 7b0a 0000 0000 0000 length) {.......
0000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000060: 0000 0000 0000 0000 4102 0000 0000 0000 ........A.......
0000070: 8824 adfb 0000 0000 0a90 46e2 207f 0000 .$........F. ...
2.2) When I run fdump with an offset of 500 and a size of 128, I again size
a chart that contains many hex values. Here there are more values from the
extension piece and more zero hex values on the top row.
PAYLOAD HEXDUMP:
0000000: 0000 0000 1000 0000 0000 0000 52e5 7464 ............R.td
0000010: 0400 0000 100e 0000 0000 0000 100e 6000 ..............`.
0000020: 0000 0000 100e 6000 0000 0000 f001 0000 ......`.........
0000030: 0000 0000 f001 0000 0000 0000 0100 0000 ................
0000040: 0000 0000 2f6c 6962 3634 2f6c 642d 6c69 ..../lib64/ld-li
0000050: 6e75 782d 7838 362d 3634 2e73 6f2e 3200 nux-x86-64.so.2.
0000060: 0400 0000 1000 0000 0100 0000 474e 5500 ............GNU.
2.3) The output of 2.1 and 2.2 are very similiar looking but contain very different
meanings. Both of the files hold some type of binary encodings because they
have hex values in the left side of the chart. ON the right side of the chart,
only the 2.1 chart has readable information. It depicts the length in the top
row while in 2.2 there is just random characters. I belive this is becaus the 2.1
reads in a c file and the parameter for fdump is to read in a C array,
while the file being read in for 2.2 is not a c file.
2.4) The file command will take in a file and then return the file type. Therefore
the following files are the following types:
/usr/bin/file: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=227b03382b7bbb9f1dc71af7cf6c5c9943799bd8, stripped
work: PDF document, version 1.3
beauty: JPEG image data, JFIF standard 1.01, comment: "CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 90"
hexdump.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
hexdump.h: C source, ASCII text
/*
* CSCI 315 Operating Systems Design
* Original developed by CSCI 315 staff
* Modified by: L. Felipe Perrone
* Date: 2011-4-21
* Copyright (c) 2011 Bucknell University
*
* Permission is hereby granted, free of charge, to any individual or
* institution obtaining a copy of this software and associated
* documentation files (the "Software"), to use, copy, modify, and
* distribute without restriction, provided that this copyright and
* permission notice is maintained, intact, in all copies and supporting
* documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL BUCKNELL UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "read_dir.h"
// function prototypes
void process(char *name);
void enqueue(char *name, que_t *q);
void dequeue(que_t *q);
void peek_front(char *name,que_t q);
bool queue_empty(que_t q);
void initq(que_t *q);
// main function
int main(int argc,char *argv[]) {
if (2 != argc) {
printf(" usage: %s dirpath\n", argv[0]);
exit(-1);
}
else {
// pass in the starting directory
process(argv[1]);
}
return 0;
}
// traverse a directory tree applying a function when a file is found
void process(char *root)
{
int numOfFiles = 0;
que_t nameq;
char dname[MAXLENGTH];
char cname[MAXLENGTH];
char prefix[MAXLENGTH];
struct dirent *dp;
DIR *dirp;
initq(&nameq);
enqueue(root,&nameq);
while (true != queue_empty(nameq)) {
peek_front(dname,nameq);
dequeue(&nameq);
dirp = opendir(dname);
if (dirp != NULL) { // it is a directory
printf("directory : %s\n",dname);
strncpy(prefix, dname, MAXLENGTH);
strncat(prefix,"/", MAXLENGTH);
for (dp = readdir(dirp); NULL != dp; dp = readdir(dirp)) {
if ((strcmp(dp->d_name,"..") != 0) &&
(strcmp(dp->d_name,".") != 0)) {
// prevent from infinite loop
strncpy(cname, prefix, MAXLENGTH);
// concatenate the prefix
strncat(cname, dp->d_name, MAXLENGTH);
enqueue(cname,&nameq);
}
}
closedir (dirp);
} else {
// test if it is a regular file and not a device or link -- TO-DO
// if this is a regular file, then process it -- TO-DO
printf(" processing file: %s\n", dname);
numOfFiles++;
}
} // while
printf(" a total of %d files were counted\n",numOfFiles);
}
// initialize queue data structure
void initq(que_t *q) {
q->head = q->tail = NULL;
}
// test whether queue data structure is empty
bool queue_empty(que_t q) {
if (NULL == q.head) {
return true;
} else {
return false;
}
}
// add an element to queue
void enqueue(char *name, que_t *q) {
item_t *temp;
temp = (item_t *)malloc(sizeof(item_t));
strncpy(temp->name,name,MAXLENGTH);
temp->next = NULL;
if (true == queue_empty(*q)) {
q->head = temp;
q->tail = temp;
} else {
q->tail->next = temp;
q->tail = q->tail->next;
}
}
// remove an element from the front of the queue
void dequeue(que_t *q) {
item_t *temp;
if (true == queue_empty(*q)) {
printf(" error in dequeue \n");
exit(-1);
} else {
temp = q->head;
q->head = q->head->next;
free(temp);
}
}
// find element at front of queue without removing
void peek_front(char *name, que_t q) {
if (true == queue_empty(q)) {
printf(" error in dequeue \n");
exit(-1);
} else {
strncpy(name, q.head->name, MAXLENGTH);
}
}
/*
* CSCI 315 Operating Systems Design
* Original developed by CSCI 315 staff
* Modified by: L. Felipe Perrone
* Date: 2011-4-21
* Copyright (c) 2011 Bucknell University
*
* Permission is hereby granted, free of charge, to any individual or
* institution obtaining a copy of this software and associated
* documentation files (the "Software"), to use, copy, modify, and
* distribute without restriction, provided that this copyright and
* permission notice is maintained, intact, in all copies and supporting
* documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL BUCKNELL UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdbool.h>
#define MAXLENGTH 255 // for file names
#define BYTE 8
struct item_type
{
char name[MAXLENGTH];
int count;
struct item_type *next;
};
struct que_type
{
struct item_type *head, *tail;
};
typedef struct que_type que_t;
typedef struct item_type item_t;
Only prelab and question 3 run properly.....honestly dont even bother with the others....I know I am going to get
a 38 on this Lab
File added
/*
* CSCI 315 Operating Systems Design
* Author: L. Felipe Perrone
* Date: 2010-02-16
* Copyright (c) 2011 Bucknell University
*casey
* Permission is hereby granted, free of charge, to any individual
* or institution obtaining a copy of this software and associated
* documentation files (the "Software"), to use, copy, modify, and
* distribute without restriction, provided that this copyright
* and permission notice is maintained, intact, in all copies and
* supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL BUCKNELL UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wrappers.c"
#define BUFFER_SIZE 512 // length of message buffer
#define QLEN 6 // length of request queue
#define FOREVER 1
#define TRUE 1
#define FALSE 0
int num_requests = 0; // tally of client requests
/*------------------------------------------------------------------------
* Program: echod - a server for echo requests
*
* Purpose: repeatedly execute the following:
* (0) wait for a connection request from client
* (1) wait for a null-terminated string from client
* (2) send back the same string to client
* (3) close the connection
* (4) go back to step (0)
*
* Usage: echod [ port ]
*
* port - a port number in user space
*
*------------------------------------------------------------------------
*/
int
main (int argc, char* argv[]) {
struct sockaddr_in sad; // structure to hold server's address
struct sockaddr_in cad; // structure to hold client's address
int sd, sd2; // socket descriptors
int port; // protocol port number
socklen_t alen; // length of address
char in_msg[BUFFER_SIZE];
char read_msg1[BUFFER_SIZE];
// buffer for incoming message
// prepare address data structure
// The memset call is ESSENTIAL!
// if you don't do this every time you create a sockaddr struct, you will
// see some pretty strange behaviour
memset((char *)&sad,0,sizeof(sad)); // zero out sockaddr structure
sad.sin_family = AF_INET; // set family to Internet
sad.sin_addr.s_addr = INADDR_ANY; // set the local IP address
// verify usage
if (argc > 1) {
port = atoi(argv[1]);
}
else {
printf("Usage: %s [ port ]\n", argv[0]);
exit(-1);
}
if (port > 0)
// test for illegal value
sad.sin_port = htons((u_short)port);
else {
// print error message and exit
fprintf(stderr,"ECHOD: bad port number %s\n", argv[1]);
exit(-1);
}
// create socket
sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sd < 0) {
perror("ECHOD: socket creation failed");
exit(-1);
}
// assign IP/port number to socket where connections come in
if (bind(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
perror("ECHOD: bind failed");
exit(-1);
}
// set up socket to receive incomming connections
if (listen(sd, QLEN) < 0) {
perror("ECHOD: listen failed");
exit(-1);
}
// main server loop - accept and handle requests
while (FOREVER) {
alen = sizeof(cad);
if ( (sd2 = accept(sd, (struct sockaddr *)&cad, &alen)) < 0) {
perror("ECHOD: accept failed\n");
exit(-1);
}
num_requests++;
// receive the string sent by client
//char write_msg[BUFFER_SIZE];
recv(sd2,&in_msg, BUFFER_SIZE, 0);
printf("done");
printf("Received:%s\n", in_msg);
// Read(parent_to_child[READ_END], &read_msg, BUFFER_SIZE);i
strcpy(read_msg1, "");
char* str1 = " ";
char* str2 = strtok(in_msg, str1);
while(str2!= NULL){
printf("Words in String:%s\n", str2);
strcat(read_msg1, str1);
strcat(read_msg1, str2);
str2 = strtok(NULL, str1);
}
send(sd2, &read_msg1, BUFFER_SIZE, 0);
Close(sd2);
}
}
/*CSCI 315 Operating Systems Design
* Author: L. Felipe Perrone
* Date: 2014-09-21
* Copyright (c) 2014 Bucknell University
*
* Permission is hereby granted, free of charge, to any individual
* or institution obtaining a copy of this software and associated
* documentation files (the "Software"), to use, copy, modify, and
* distribute without restriction, provided that this copyright
* and permission notice is maintained, intact, in all copies and
* supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL BUCKNELL UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "wrappers.c"
#define BUFFER_SIZE 512
#define TRUE 1
#define FALSE 0
/*------------------------------------------------------------------------
* Program: echoreq
*
* Purpose: allocate a socket, connect to a server, transfer requested
* file to local host, and print file contents to stdout
*
* Usage: echoreq [ host ] [ port ] [ string ]
*
* host - name of a computer on which server is executing
* port - protocol port number server is using
* string - a string in double quotes
*
*------------------------------------------------------------------------
*/
int
main(int argc, char* argv[]) {
struct hostent *ptrh; // pointer to a host table entry
struct sockaddr_in sad; // structure to hold an IP address
int sd; // socket descriptor
int port; // protocol port number
char *host; // pointer to host name
char in_msg[BUFFER_SIZE]; // buffer for incoming message
int ret_val;
sad.sin_family = AF_INET; // set family to Internet
// verify usage
if (argc < 4) {
printf("Usage: %s [ host ] [ port ] [ string ]\n", argv[0]);
exit(-1);
}
host = argv[1];
port = atoi(argv[2]);
if (port > 0)
// test for legal value
sad.sin_port = htons((u_short)port);
else {
// print error message and exit
printf("ECHOREQ: bad port number %s\n", argv[2]);
exit(-1);
}
// convert host name to equivalent IP address and copy to sad
ptrh = gethostbyname(host);
if ( ((char *)ptrh) == NULL ) {
printf("ECHOREQ: invalid host: %s\n", host);
exit(-1);
}
memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);
// create socket
sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sd < 0) {
printf("ECHOREQ: socket creation failed\n");
exit(-1);
}
// connect the socket to the specified server
if (connect(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
perror("ECHOREQ: connect failed");
exit(-1);
}
// send message to server
char write_msg[BUFFER_SIZE];
strcpy(write_msg, argv[3]);
send(sd, &write_msg, BUFFER_SIZE, 0);
printf("sent");
// send the received string back to client
printf("\n");
// //send(sd, buf, len flags);
strcpy(in_msg, "");
recv(sd, in_msg, BUFFER_SIZE, 0);
//
// receive message echoed back by server
printf("ECHOREQ: from server= %s\n", in_msg);
// close the socket
Close(sd);
// terminate the client program gracefully
return(0);
}
Lab 4 feedback
Prelab 1 (pipes vs open): 5/5
Prelab 2 (mytime.c): 25/25
1) TCP 4/4
2) bind 4/4
3) connect 4/4
4) listen 4/4
5) accept 4/4
6) question 5/5
Problem 1: 7/10
wrappers contains all 12 functions 7/10
(Fork, Pipe, Wait, WaitPid, Open, Close,
Write, Read, Connect, Bind, Listen, Accept,
Send, Recv, Socket)
-3: Missing Send, Recv, and Socket
Note: Use
Problem 2: 25/25
messages are "cleaned up" by the server 15/15
wrapper functions are used 10/10
Problem 3: 20/20
1) how is it interprocess without forks? 4/4
2) who gave you the socket 4/4
3) sockets vs pipes when to use 4/4
4) gethostbyname 4/4
5) replacement for gethostbyname 4/4
Problem 4: 7/10
use new command 7/10
-3: If does not send and recive messages
Not sure why but prints out usage statment when trying to run
Total: 94/100
Create a file called answers.txt in which you explain why rand_r is thread safe.
Rand_r() will return a psuedo-random intger from 0 to the preset max. The rand_r will take in a unsigned integer which is named the seed. The argument is a pointer to the seed for the sequence of random numbers. When you call the rand_r with the same seed value you will recieve the same sequence. The rand_r does not change or read in anything other than the arguments. The rand_r will ensure that different threads use different seed arguments.
Lab 5 feedback
Prelab 1 (circular-list):
convinces me that it works 20/20
Prelab 2 (answers):
1) mutex vs semaphore 4/4
2) lib calls 6/6
Problem 2:
Values produced by rand_r appear random 10/10
Problem 3:
explain why rand_r is thread safe 10/10
Problem 4:
using semaphore properly 15/15
using mutex properly 15/15
Problem 5:
program fails on improper command line arguments5/10
-5: segmentation fault with 0 arguments
program runs without bugs 10/10
Total: 95/100
/*
* Copyright (c) 2013 Bucknell University
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: L. Felipe Perrone (perrone@bucknell.edu)
*/
#ifndef _CIRCULAR_LIST_H_
#define _CIRCULAR_LIST_H_
#include <semaphore.h>
#include <pthread.h>
typedef double item;
/** Circular list ADT. This circular list is implemented as a
* bounded buffer for use in multi-threaded applications.
*/
struct circular_list {
int start; /// index of the first occupied position in buffer
int end; /// index of the last occupied position in buffer
int elems; /// number of elements currently held in buffer
int size; /// capacity of the buffer
item *buffer; /// array of buffer items
pthread_mutex_t lock;
sem_t full;
sem_t empty;
};
/**
* Create a circular list with a pre-defined buffer size.
* @param l pointer to a circular list ADT
* @param size number of items to allocate in circular list
* @return 0 if successful, -1 if any error condition is found
*/
int circular_list_create(struct circular_list *l, int size);
/**
* Insert item into the circular list.
* @param l pointer to a circular list ADT
* @param i item to copy into a position of the circular list
* @return 0 if successful, -1 if any error condition is found
*/
int circular_list_insert(struct circular_list *l, item i);
/**
* Remove item from the circular list.
* @param l pointer to a circular list ADT
* @param i pointer to an item onto which the removed item is copied
* @return 0 if successful, -1 if any error condition is found
*/
int circular_list_remove(struct circular_list *l, item *i);
#endif /* _CIRCULAR_LIST_H_ */
......@@ -18,48 +18,95 @@
*/
#include <stdlib.h>
#include "circular-list.h"
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <semaphore.h>
#include "circular-list.h"
int circular_list_create(struct circular_list *l, int size) {
// mutex initialization
pthread_mutex_init(&l->lock, NULL);
//semaphores
sem_init(&l->empty, 0, size);
sem_init(&l->full, 0, 0);
l->buffer = calloc(size, sizeof(item));
l->start = 0;
l->end = 0;
l->start = -1;
l->end = -1;
l->elems = 0;
l->size = size;
return 0;
}
int circular_list_insert(struct circular_list *l, item i) {
//semaphore
sem_wait(&l->empty);
//mutex
pthread_mutex_lock(&l->lock);
if(l->elems == l->size ){ //
return -1;
}
else {
}
if (l->elems == 0){
l->end = 0;
}
l->start += 1;
if (l->start == l->size){
l->start = 0;
}
//int len = l->size;
l->buffer[l->end] = i;
l->buffer[l->start] = i;
//l->end += 1;
l->end = (l->end+1) % l->size;
//l->end = (l->end+1) % l->size;
l->elems += 1;
//mutex
pthread_mutex_unlock(&l->lock);
//semaphore
sem_post(&l->full);
return 0;
}
}
int circular_list_remove(struct circular_list *l, item *i) {
if(l->end == 0){
//semaphore
sem_wait(&l->full);
//mutex
pthread_mutex_lock(&l->lock);
if(l->elems == 0){
printf("Empty List!!!");
return -1;
}
l->elems -= 1;
// else{
*i = l->buffer[l->start];
*i = l->buffer[l->end];
//l->start += 1;
l->start = (l->start+1) % l->size;
l->elems -= 1;
l->buffer[l->end] = -1;
l->end += 1;
if(l->end == l->size){
l->end = 0;
}
return 0;
//}
//mutex
pthread_mutex_unlock(&l->lock);
//semaphore
sem_post(&l->empty);
return *i;
}
/*
* Copyright (c) 2013 Bucknell University
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: L. Felipe Perrone (perrone@bucknell.edu)
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include "circular-list.h"
/* SCALE_FACTOR is a constant for you to experiment with:
* if you choose a very large SCALE_FACTOR, your threads
* might spend a long time sleeping. If you choose it to be
* too small, your threads will not sleep at all. Note
* that in the producer and consumer functions, the sleep
* time is computed as the INTEGER DIVISION below:
*
* usleep(SCALE_FACTOR * rand_r(&seed) / RAND_MAX
*
* where RAND_MAX is the largest random numver returned
* by rand_r. If the numerator is smaller than RAND_MAX,
* the quotient of the integer division is ZERO!
*/
#define SCALE_FACTOR 1000
// global variables -----------------------
struct circular_list mylist;
// end of global variables ----------------
void *producer (void *param) {
item i;
unsigned int *seed = (unsigned int *) param;
while (true) {
// sleep for random period of time
usleep(SCALE_FACTOR * (rand_r(seed)) / RAND_MAX);
// generate a random number
i = (item) (((double) (rand_r(seed))) / RAND_MAX);
if (circular_list_insert(&mylist, i) == -1) {
printf("PRODUCER: error condition\n");
} else {
printf("PRODUCER: produced value %lf\n", i);
}
}
}
void *consumer (void *param) {
item i;
//unsigned int seed = 999;
unsigned int *seed = (unsigned int *) param;
while (true) {
// sleep for random period of time
usleep(SCALE_FACTOR * (rand_r(seed)) / RAND_MAX);
if (circular_list_remove(&mylist, &i) == -1) {
printf("CONSUMER: error condition\n");
} else {
printf("CONSUMER: consumed value %lf\n", i);
}
}
}
int main (int argc, char *argv[]) {
// get command line arguments
//strcopy(producer, argv[1]);
//strcopy(consumer, argv[2]);
//strcopy(usleep, argv[3]);
int num_producers = atoi(argv[1]);
int num_consumers = atoi(argv[2]);
int sleep_time = atoi(argv[3]);
// if error in command line argument usage, terminate with helpful
// message
if (argc < 4){
printf("Not enough arugments!!! Format: prodcons num_prod num_cons sleep_time");
exit(-1);
}
// initialize buffer
circular_list_create(&mylist, 20);
// create producer thread(s)
int prodt;
pthread_t prod_tid[num_producers];
int prod_seed[num_producers];
for (prodt = 0; prodt < num_producers; prodt++) {
prod_seed[prodt] = prodt + 400;
pthread_create(&prod_tid[prodt], NULL, producer, &prod_seed[prodt]);
}
// create consumer thread(s)
pthread_t con_tid[num_consumers];
int cont_seed[num_consumers];
for (prodt = 0; prodt < num_consumers; prodt++) {
cont_seed[prodt] = prodt + 400;
pthread_create(&con_tid[prodt], NULL, consumer, &cont_seed[prodt]);
}
// sleep to give time for threads to run
sleep(sleep_time);
// exit
return (0);
}
CC = gcc
CFLAGS = -std=gnu99 -Wall -g #-DDEBUG
EXECS = dp
all: $(EXECS)
dp: dp.c
$(CC) $(FLAGS) dp.c -o dp -pthread
problem1: problem1.c
$(CC) $(FLAGS) problem1.c -o problem1 -pthread
.PHONY: clean
clean:
/bin/rm -rf $(EXECS)
1.1
After running my code for about 10 seconds, I do not see any issues. The things that I see are philopshers doing different actions like napping, eating and finsihing eating. I also do see the same philopsher doing these actions for a few times in a row. This follows the idea tho that no 2 philosophers should be sitting next to each other and eating at the same time.
1.2
The ways to achieve deadlock is:
1) is to ensure that the processes must be unsharable so here that means that 2 philosphers will not be able to use one chopstick at one time
2) is to ensure that a processes is waiting on another rescourse so here that means that one philopsher is waiting on another pphilopsher to be able to use the chopstick and eat
3) is to ensure that the processes cannot be interupted so here this means that a philopsher cannot stop another philopsher and take his chopstick
4) the must be multiples processes so here that means there are numerous philopshers which is true.
2.1 The situation that lead me to dead lock is adding napping calls after each of the mutex locks! I also increased the napping time while eating. This created a deadlock where each philopsopher picked up a chopstick but did not begin to eat. Then if a philopsopher was actually allowed to start eating, the others had to wait so long for him to finish that there became a deadlock.
3.1
These solutions do not eliminate all potential causes of deadlock. When i run this code numerous times, I still see bouts of deadlock. I beleive this is due to the fact that the napping calls are frequent and the one when the eating happens is long. Therefore the philopshers are waiting so long to eat and therefore once the philopshers pick up a chopstick each, it runs in to deadlock.3.1
These solutions do not eliminate all potential causes of deadlock. When i run this code numerous times, I still see bouts of deadlock. I beleive this is due to the fact that the napping calls are frequent and the one when the eating happens is long. Therefore the philopshers are waiting so long to eat and therefore once the philopshers pick up a chopstick each, it runs in to deadlock.3.1
These solutions do not eliminate all potential causes of deadlock. When i run this code numerous times, I still see bouts of deadlock. I beleive this is due to the fact that the napping calls are frequent and the one when the eating happens is long. Therefore the philopshers are waiting so long to eat and therefore once the philopshers pick up a chopstick each, it runs in to deadlock.
/*
* Copyright (c) 2013 Bucknell University
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: L. Felipe Perrone (perrone@bucknell.edu)
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
#include <string.h>
/* SCALE_FACTOR is a constant for you to experiment with:
* if you choose a very large SCALE_FACTOR, your threads
* might spend a long time sleeping. If you choose it to be
* too small, your threads will not sleep at all. Note
* that in the producer and consumer functions, the sleep
* time is computed as the INTEGER DIVISION below:
*
* usleep(SCALE_FACTOR * rand_r(&seed) / RAND_MAX
*
* where RAND_MAX is the largest random numver returned
* by rand_r. If the numerator is smaller than RAND_MAX,
* the quotient of the integer division is ZERO!
*/
#define SCALE_FACTOR 1000
// global variables -----------------------
//static pthread_mutex_t chopsticks[5];
int phils[5] = {0, 1, 2, 3, 4};
// end of global variables ----------------
void napping(int x) {
unsigned int seed1 = pthread_self();
int count = rand_r(&seed1) % (x+1);
sleep(count);
}
void *philosopher (void *param) {
//item i;
long long param_long = (long long)param;
int i = (int)param_long;
while (1==1) {
// sleep for random period of time
// usleep(SCALE_FACTOR * (rand_r(seed)) / RAND_MAX);
printf("Philospher %d : thinking. \n", i);
napping(2);
printf("Philospher %d : hungry. \n", i);
//pthread_mutex_lock(chopsticks[i]);
//pthread_mutex_lock(chopsticks[(i+1) % 5]);
printf("Philospher %d : starting to eat. \n", i);
napping(1);
printf("Philospher %d : done eating. \n", i);
//pthread_mutex_unlock(choptsticks[i]);
//pthread_mutex_unlock(chopsticks[(i+1) % 5]);
}
}
int main() {
// get command line arguments
//strcopy(producer, argv[1]);
//strcopy(consumer, argv[2]);
//strcopy(usleep, argv[3]);
int phils = 5;
int i;
pthread_t threads[phils];
long long tid;
for (i = 0; i < phils; i++){
tid = (long long)i;
pthread_create(&threads[i], NULL, philosopher, (void*)tid);
}
sleep(10);
return 0;
}
------------------------------------------------------------