Pointers about pointers Announcements Midterm next week pointer is - - PDF document

pointers about pointers announcements
SMART_READER_LITE
LIVE PREVIEW

Pointers about pointers Announcements Midterm next week pointer is - - PDF document

Pointers about pointers Announcements Midterm next week pointer is a memory address Material covered up until June 18 (last week, is 4 bytes like an unsigned int signals) can address up to 2^32 bytes = 4 gb Allowed to have


slide-1
SLIDE 1

1

Announcements

Midterm next week Material covered up until June 18 (last week,

signals)

Allowed to have 1 cheat sheet No tutorial Come to class at 6 Test is 6:10 – 7:00 Assignment 3 is on the web site

Pointers about pointers

pointer is a memory address is 4 bytes like an unsigned int can address up to 2^32 bytes = 4 gb declaring a pointer allocates 4 bytes for the

pointer itself - that's it! char * ptr; gets(ptr);

will compile, but crash

Pointer type

pointers are typed char * pchar; vs. int * pint,

struct mystruct * pstruct;

similarity: all are 4 bytes difference: pchar++; //increment by 1 byte pint++; //increment by 4 bytes pstruct++; //increment by sizeof(mystruct)

Example

char * pchar; int * pint; struct mystruct * pstruct; int arry[3][3] = { {1,2,3}, {4,5,6}, {7,8,9}}; pchar = (char *)arry; pint=(int *)arry; pstruct=(struct mystruct *)arry; printf("pchar=%p,pint=%p,pstruct=%p\n",pchar,pint,pstruct); pchar+=1; pint+=1; pstruct+=1; printf("pchar=%p,pint=%p,pstruct=%p\n",pchar,pint,pstruct); pchar=0012FF50,pint=0012FF50,pstruct=0012FF50 pchar=0012FF51,pint=0012FF54,pstruct=0012FF58

slide-2
SLIDE 2

2

Arrays

The name of an array is the memory address of the

array

It is a const pointer - cannot do arithmetic on it:

char buf[100]; buf=buf+1; //illegal!

but you can do this:

char * ptr; ptr=buf; ptr+= 50; //points half way through this array.

Multi-dimensional arrays

int twodbuf [3][3]; allocates contiguous chunk of memory that is

3x3xsizeof(int)=36 bytes

twodbuf is of type int ** In other words: twdbuf is an array of int * so twodbuf[i] is of type int * (twodbuf[i])[j] is of type int

Example:

arry == 0x12ff50 0012FF50 01 00 00 00 02 00 00 00 03 00 00 00 ............ 0012FF5C 04 00 00 00 05 00 00 00 06 00 00 00 ............ 0012FF68 07 00 00 00 08 00 00 00 09 00 00 00 ............ 0012FF74 CC CC CC CC 50 FF 12 00 50 FF 12 00 ÌÌÌÌPÿ..Pÿ..

Truth about multi-dimensional arrays

No such thing. A 2d array is just made up of a bunch of 1D

arrays

There are only really ever 1D arrays

slide-3
SLIDE 3

3

Dynamic allocation (2D arrays)

allocate 2d array of dimension: row,col of chars easyway (works only is col is same for every row): char * ptr=new char [row*col];//or ptr=(char*)malloc(row*col*sizeof(char)); //index the i,j element: char * pij = ptr + i*col + j; //harder, more general way. works even if col is not the same for every row. char ** ptr; ptr = new char * [row]; // or ptr=(char **)malloc(row*sizeof(char *)); for(i=0;i<row;i++) { ptr[i]= new char[col]; // or ptr[i]= (char )malloc(col*sizeof(char)); } //index i,j element: ptr[i][j]

parameter passing

When you pass an array, you really just pass the

pointer:

void myfunc(char * arry) is the same as void myfunc(char arry[]) pointers are passed by value!

Consider:

void assignptr(char * dst,char * src) { dst=src; } char arry[10],* ptr; assignptr(ptr,arry);//does nothing. //how to fix??

Make files

Why Makefiles? Up until now, we've built projects using shell scripts Complete rebuild everytime something changes Ok for small projects But for large projects (10s of thousands of files,

millions of lines of code) a rebuild is NOT ok

Build ONLY what's needed (incremental build)

Dependency tracking

Need to know: if I change a file, which other

file(s) need to be updated too?

Example: change a #define in a .h file, then

all files that include the .h need to be recompiled

Makefiles and the make utility allows you to

do this

slide-4
SLIDE 4

4

make

The make utility updates a bunch of files

according to dependency stored in a "makefile"

make -f mymakefile

  • r just

make If no file specified, automatically look for

"makefile"

General format of a makefile

The general format is:

target: depdency1,dependency2... <tab> <how to create target based on dependencies> dependency1: <more dependencies> <tab><how to create dependency1> ...

Example

main1: main1.o reverse.o g++ -omain1 main1.o reverse.o main1.o: main1.cpp reverse.h g++ -c main1.cpp reverse.o: reverse.cpp reverse.h g++ -c reverse.cpp

Dependency tree of the above

slide-5
SLIDE 5

5

touch

make works by looking at time stamps if any dependencies have a newer time

stamp, the target needs to be rebuilt

Traces dependencies up the tree If after a full build you say "make", then

nothing happends

use touch to update the time stamp

clean

The above rules leave a lot of .o files around Usually, there is a "clean" rule:

clean: rm -f *.o

removes all the intermediate files but any build after this will be a full build

Inter-process Communication

Pipes (Haviland – Ch. 7)

Inter-Process Communication (IPC)

Data exchange techniques between processes:

message passing: files, pipes, sockets shared-memory model

Limitations of files for IPC

slow, others can modify files

Limitations of pipes

two processes must be related and running on the same

machine.

Limitations of sockets

full network protocol stack required from PF_INET

(necessary if the processes are on different machines)

PF_LOCAL similar to pipes – better performance than

PF_INET between processes on the same machine

slide-6
SLIDE 6

6

Producer/Consumer Problem

Simple example: who | wc –l Both the writing process (who) and the

reading process (wc) of a pipeline execute concurrently.

A pipe is usually implemented as an internal

OS buffer.

It is a resource that is concurrently accessed

by the reader and the writer, so it must be managed carefully.

Producer/Consumer

consumer should be blocked when buffer is empty producer should be blocked when buffer is full producer and consumer should run independently

as far as buffer capacity and contents permit

producer and consumer should never be updating

the buffer at the same instant (otherwise data integrity cannot be guaranteed)

producer/consumer is a harder problem if there are

more than one consumer and/or more than one producer.

File Descriptors Revisited

Used by low-level I/O

  • pen(), close(), read(), write()

declared as an integer

int fd;

Not the same as a “file stream”: FILE *fp; A useful system call to convert a stream to a fd

int fileno( FILE *fp);

Of course it is possible to assign a stream interface

to a file descriptor FILE *fdopen(int fd, const char *mode);

pipe()

Create pipe with:

int pipe(int filedes[2])

filedes is a 2 integer array that holds the file

descriptors for each end of the pipe

filedes[0] is open for reading filedes[1] is open for writing The pipe is just an internal OS buffer Data treated in FIFO (first in, first out) basis lseek() will not work on pipes

slide-7
SLIDE 7

7

Simple example:

...other declarations... int p[2]; if(pipe(p)==-1) { ...print error, quit... } write(p[1],msg1,MSGSIZE); write(p[1],msg2,MSGSIZE); //read it back for(j=0;j<2;j++) { read(p[0],inbuf,MSGSIZE); printf("%s\n",inbuf); } ...rest of program pipe kernel fd[1] fd[0] user process

int pipe(int filedes[2])

half-duplex

(one-way) communication

write read

Pipes only useful with fork()

Recall file descriptors remain open across a fork()

call

int p[2]; if(pipe(p)==-1) { ...print error, quit... } if(!fork()) { write(p[1],msg1,MSGSIZE); write(p[1],msg2,MSGSIZE); } else { //read it back for(j=0;j<2;j++) { read(p[0],inbuf,MSGSIZE); printf("%s\n",inbuf); } } ...rest of program

What happens after fork?

user process user process kernel fd[1] fd[0] fd[1] fd[0] pipe

slide-8
SLIDE 8

8

Direction of data flow?

parent child kernel fd[1] fd[0] fd[1] fd[0] pipe child to parent close fd[1] in parent and fd[0] in child) parent to child (close fd[0] in parent and fd[1] in child)

Pipes and File Descriptors

A forked child inherits file descriptors from its

parent

pipe() creates an internal system buffer and

two file descriptors, one for reading and one for writing.

After the pipe call, the parent and child

should close the file descriptors for the

  • pposite direction. Leaving them open does

not permit full-duplex communication.

Correct code

int p[2]; if(pipe(p)==-1) { ...print error, quit... } if(!fork()) { close(p[0]); write(p[1],msg1,MSGSIZE); write(p[1],msg2,MSGSIZE); } else { close(p[1]); //read it back for(j=0;j<2;j++) { read(p[0],inbuf,MSGSIZE); printf("%s\n",inbuf); } } ...rest of program

dup2()

Often we want the stdout of one process to

be connected to the stdin of another process.

Point one FD to the location pointed to by the

  • ther FD

returnCode = dup2( oldFD, newFD );

newFD and oldFD now refer to the same file if newFD is open, it is first automatically closed Note that dup2() refer to fds not streams

slide-9
SLIDE 9

9

dup2()

newfd

  • ldfd
  • ldfd = open(“file”);

dup2(oldfd, newfd); “file” Process

pipe()/dup2() example

/* equivalent to “sort < file1 | uniq” */ int fd[2]; int filedes = open(“file1”, O_RDONLY); dup2(filedes, fileno(stdin)); pipe(fd); if(fork() == 0) { dup2(fd[1], fileno(stdout)); close(fd[0]); close(fd[1]); execl(“/usr/bin/sort”, “sort”, (char *) 0); } else { dup2(fd[0], fileno(stdin)); close(fd[1]); close(fd[0]); execl(“/usr/bin/uniq”, “uniq”, (char *) 0); }

Direction of data flow?

parent child fd[1] fd[0] fd[1] fd[0] kernel pipe file1 filedes stdin stdout filedes stdin stdout sort uniq

  • pen

pipe fork dup2 close dup2 dup2

Reading and writing to a pipe

A read on an empty pipe will block until there is

something to read.

A write on a full pipe will block until there is more

  • space. (Pipes have a finite size.)

Writing to a pipe that has been closed by the other

end will result in a SIGPIPE or “Broken Pipe” message.

Read will return 0 if the write end of the pipe is

closed.

slide-10
SLIDE 10

10

popen() and pclose()

popen() simplifies the sequence of:

generating a pipe forking a child process duplicating file descriptors passing command execution via an exec()

Usage:

FILE *popen( const char *command, const char *type );

Example:

FILE *pipeFP; pipeFP = popen(“/usr/bin/ls *.c”, “r”);

popen()

pipe pipe Us Command Command Us “r” “w”