Title: Today
1Lecture 26
- Today
- Increment and Decrement operators
- DLLs
- Unix Processes -- fork()
- exec() in Unix
- CreateProcess in Windows
- Announcements
- Project 6 (Kalah) due 9pm Monday after
Thanksgiving - Project 7 Due immediately after (In class
Tues/Thurs). - 100 if shown to me in class (Tuesday/Thursday).
80 thru email submission. Note All projects
must still be submitted via email.
2Overloading --
- What are some properties of and - - we will
need to maintain when we overload these? - Question 1 What does it mean to increment or
decrement concerning the type we want to or - Question 2 Where are the and - - ops used?
- Question 3 Is it prefix or postfix
- A How do we tell the difference between the two
- B What should it return and when
3Consider a Fraction class
- Observation1 Incrementing a Fraction means
adding the value of the denominator to the
numerator - Observation2 Can be stand-alone, or inside
another expression that means it needs to return
a value - C tells us how to write these methods so the
compiler can tell the difference - Prefix takes no parameters
- Postfix takes a dummy integer parameter
- Prefix should return the changed value
- Postfix should return value before it is changed
4Prefix and Postfix
- Fraction operator()
- //prefix
- this-gtnumthis-gtden
- return this
-
- Fraction operator(int)
- //postfix
- Fraction temp this
- this-gtnumthis-gtden
- return temp
5Homework Exercise
- Modify Zip13
- Add the code for the operators that we just
did. - Add the code for the - - operators as well.
- Take off the int parameter on the postfix
operations and see what kind of error you get
(compile, link, name) - Make the or -- friend functions rather than
methods.
6Building using components
- Components can mean different things
- Subprogram
- Class
- DLL (Dynamic Link Library)
- COM (Common Object Model)
- CORBA (Common Object Request Broker Architecture)
- First two imply source code as components
- Last three utilize binary code as components
7Source Binary Components
- Class (source-based) approach
- Build source code in individual components
- Link these components together
- Must rebuild the entire system every time a
component is changed/modified - Binary components are treated as separate units
at the executable (system) level - Example DLL files
- The application links to appropriate DLLs as
needed during execution (at run-time)
8Benefits to Binary Components
- Applications can share components
- Less disk space required for applications
- Components can be reused in applications
- Upgrades to a component do not require
recompilation of the applications - Can upgrade applications by simply upgrading
individual components, but be careful! - Upgrading an implementation of a DLL is fine
- Upgrading the interface can be dangerous
- Why?
9Consider an example with DLLs
- Simple windows painting program
- Left click draws randomly colored/sized rectangle
- Right click draws randomly colored/sized ellipse
- OnPaint redraws as needed
- Define a new data type to store information about
each shape - Need location, size, color, ellipse or rectangle
- Use a vector of this data type in our application
10Build this application with DLLs
- 1st Build the DLL (the new data type)
- Built in its own MFC project
- Need to create a .lib file
- Need to create a .dll file
- 2nd Build the application
- A different (second) MFC project
- Must link in references to DLL object
- Include header file for compilation
- Include .lib file for linking state
11Building the DLL
- In VC, select
- New
- Project
- Win32 Dynamic Link Library
- Create header file
- images.h
- Note the extra stanza that must be added to the
header file - Two underscores at the start of declspec
- include ltafxwin.hgt
- class __declspec(dllexport) Images
- publicImages()COLORREF GetColor( )int
GetShape( )int GetSize( )CPoint GetPoint(
)void SetColor(COLORREF)void
SetShape(int)void SetSize(int)void
SetPoint(CPoint) - privateCOLORREF mColorint mShape,
mSizeCPoint mPoint
12Building the DLL (continued)
- include "images.h"
- ImagesImages()
- COLORREF ImagesGetColor() return mColor
- CPoint ImagesGetPoint() return mPoint
- int ImagesGetShape() return mShape
- int ImagesGetSize() return mSize
- void ImagesSetColor(COLORREF c) mColor
c - void ImagesSetPoint(CPoint p) mPoint p
- void ImagesSetShape(int s) mShape s
- void ImagesSetSize(int s) mSize s
- The body of the class simply contains the code
needed to implement all the various methods in
the class
13Building the DLL (last steps)
- Under Build menu, select build xxx.dll
- This should generate two files of interest
- xxx.dll, the binary component we are interested
in, located in the Debug directory - xxx.lib, library information that tells where the
component code exists (a link to the DLL), also
located in the Debug directory - Can now use this class in other applications
14Building our Application
- In VC
- New
- Project
- Win32 application
- Header
- Include the header for DLL class
- Keep vector of images
- include "..\ImagesDLL\images.h"
- include ltafxwin.hgt
- include ltvectorgt
- using namespace std
- class CPaintWin public CFrameWnd
- publicCPaintWin()afx_msg void
OnLButtonDown(UINT, CPoint)afx_msg void
OnRButtonDown(UINT, CPoint)afx_msg void
OnPaint() - privatevectorltImagesgt dataDECLARE_MESSAGE_MAP(
)
15Building our application (cont)
- OnLButtonDown and OnRButtonDown are similar in
nature - Get a random size
- Get a random color
- Declare a new Images object and then sets
- Color
- Size
- Shape (1rect, 2circle)
- Location
- Push this object onto our vector of Images
- //this is main.cpp
- afx_msg void CPaintWinOnLButtonDown (UINT
flags, CPoint point) - int size, r, g, bsize rand()50 10r
rand()255g rand()255b
rand()255COLORREF c RGB(r,g,b)Images
pp.SetColor(c)p.SetSize(size)p.SetShape(1)/
/2 w/right buttonp.SetPoint(point)data.push_bac
k(p)InvalidateRect(NULL)
16Building our application (cont)
- OnPaint routine runs thru the vector of Images
and draws each of them - What is bad about this?
- afx_msg void CPaintWinOnPaint( ) CPaintDC
dc(this)if ( data.empty( ) ) return // handles
initial windowvectorltImagesgtiterator afor
(adata.begin() altdata.end() a) // print
all Images CPoint p a-gtGetPoint( ) int s
a-gtGetSize( ) CBrush pBrush new CBrush(
) pBrush-gtCreateSolidBrush(a-gtGetColor( ))
if (a-gtGetShape( )1) // rectangle
dc.FillRect(CRect(p.x-s/2,p.y-s/2,p.xs/2,p.ys/2)
,pBrush) else // ellipse CPen pPen
new CPen() pPen-gtCreatePen(PS_SOLID, 1,
a-gtGetColor()) dc.SelectObject(pPen)
dc.SelectObject(pBrush) dc.Ellipse(CRect(p.x-s/
2, p.y-s/2, p.xs/2, p.ys/2))
17Compiling our application
- Project / Settings
- General Using MFC in a Shared DLL
- Link Object/Library Modules
- Must add location of DLL library file
- Example ..\ImagesDLL\Debug\ImagesDLL.lib
- If you name your dll project something else, the
names wont be the same as this example - This should allow application to compile
- To run executable, need access to the DLL file
- Must be in a known location
- Would normally want it in the system path
- Copy it to the application directory (in the
DEBUG folder)
18Class Exercises
- The files needed to generate an MFC application
using DLLs are out on the web - DLL part
- Snippita contains Images.h
- Snippitb contains Images.cpp
- Front End
- Snippitc contains PaintWin.h
- Snippitd contains PaintWin.cpp
- Build this application (using DLLs)
19Definitions (dont memorize)
- Source http//foldoc.doc.ic.ac.uk/foldoc/
- Program The instructions executed by a computer.
"Code" is closely related but not exactly the
same. The noun "program" describes a single,
complete and more-or-less self-contained list of
instructions, often stored in a single file,
whereas "code" and "software" are uncountable
nouns describing some number of instructions
which may constitute one or more programs or part
thereof. Most programs, rely heavily on various
kinds of operating system software for their
execution. - Process An executing program. A process consists
of the program code (which may be shared with
other processes which are executing the same
program), and some private data. It may have
other associated resources such as a process
identifier, open files, CPU time limits, shared
memory, child processes, and signal handlers. A
multitasking operating system can run multiple
processes concurrently or in parallel.
20Programs Processes
- Up until now, everything we have done is
- Write a program
- Run the program as a single process
- Both Unix and Windows allow multiple processes to
be running at the same time - Unix multiple users, each has their own
processes - ps ef command lists all processes on the
system - Windows single user, multiple applications
executing at the same time (browser, VC, etc.) - Task manager (CTRL-ALT-DEL) displays processes
21The ps command
- Summarize all processes running
- ps
- Individually list all processes running
- ps -ef
- List all processes of a particular user
- ps ef grep userid (ps ef grep yessi001)
- Output
- USER Proc Parent C STime TTY CPU Name
- Yessi001 3748 3742 0 165850 pts/17 000 ksh
- along with all other processes Im running
22Class Exercises
- Log onto bama.ua.edu (Unix system)
- List all the processes currently running
- ps ef command
- How many processes are there?
- Consider piping output to wc routine
- Are there cases where more than one person is
running the same program (multiple processes with
the same name)
23Programs Processes (cont)
- Programs to date
- Write one program
- It generates a single process
- Programs can also be written that
- When executed, create multiple processes
- Communicate with other processes in the system
- Future classes (OS, networks, etc.) assume some
basic understanding of programs and processes
24Unix Processes
- In Unix, a standard C program generates a
single (executable) process - Consider code at right
- Prints hello
- Invokes fork function
- Prints goodbye (twice)
- Fork creates a second (identical) instance of
this process
- include ltiostream.hgt
- include ltstdlib.hgt
- include ltunistd.hgt
- int main()
- cout ltlt "hello" ltlt endl
- fork( )
- cout ltlt "world" ltlt endl
-
- Output
- hello
- world
- world
25What happens with fork ?
- Before fork( )
- One process
- Arrow indicates current point of execution
- After fork( )
- Two separate processes
- Both at the same point in their execution (both
just completed fork( ))
int main() cout ltlt "hello" ltlt endl fork(
) cout ltlt "world" ltlt endl
int main() cout ltlt "hello" ltlt endl fork(
) cout ltlt "world" ltlt endl
int main() cout ltlt "hello" ltlt endl fork(
) cout ltlt "world" ltlt endl
26Class Exercises
- What is the output?
- include ltiostream.hgt
- include ltstdlib.hgt
- include ltunistd.hgt
- int main()
- cout ltlt "hello" ltlt endl
- fork()
- cout ltlt "world" ltlt endl
- fork()
- cout ltlt "goodbye" ltlt endl
- What is the output?
- include ltiostream.hgt
- include ltstdlib.hgt
- include ltunistd.hgt
- int main() int a 0cout ltlt "hello" ltlt
endla a 5fork()cout ltlt a ltlt endla a
5fork()fork()cout ltlt a ltlt endl
27Are these processes identical?
- After a fork
- Both at same point in execution
- Both have same values for all variables
- Both have the same file descriptors
- One difference
- One is the parent of the other (child) process
- int pidvar fork()
- Parent has process id of child, child has 0 in
pidvar - You can tell this via ps command
28Class Exercises
- Run the program at the right, it will fork off a
new process and then wait for input - While it is waiting for input, log on to bama in
a new window and typeps ef grep userid - Find these processes
- Figure out which is the parent and which is the
child
- include ltiostream.hgt
- include ltstdlib.hgt
- include ltunistd.hgt
- int main()
- int a
- cout ltlt "hello" ltlt endl
- int pidvar fork()
- cin gtgt a
- cout ltlt "world" ltlt endl
29Class Exercises
- include
- int main( )
- int a 10
- int anything fork()
- cout ltlt a ltlt endl
- coutltlt"PID is "ltltanythingltltendl //assume
child PID is 18754 - if (anything 0)
- cout ltlt this is a child ltlt endl
- cout ltlt a ltlt endl
- int anything2fork()
- if(anything20) cout ltlt this is a child of
a child ltlt endl - else cout ltlt this is a child and a parent
ltlt endl - cout ltlt a ltlt endl
-
- else
- coutltltthis is the parent and a
grandparent"ltltendl - a 5
- cout ltlt a ltlt endl
-
30Creating new processes
- How do you replace a running process with a new
process (new set of instructions) - Use the exec function
- First, create a second version of your process
- via fork( )
- Next, replace the contents of this new process
with another program - via exec( )
31Exec function
- Exec comes in many flavors (see man exec)
- We will use execl
- Specify location of new process (1st arg)
- Specify name of new process (2nd arg)
- Specify any arguments passed to new process
- Specify NULL to end parameter list (3rd arg)
- include ltiostream.hgt
- include ltstdlib.hgt
- include ltunistd.hgt
- int main( )
- cout ltlt "hello world" ltlt endl
- int pid fork()
- coutltlt"PID is "ltltpidltltendl
- if (pid 0)
- execl("/usr/bin/ls","ls",NULL)
- else
- coutltlt"original proc"ltltendl
32What happens with exec ?
- Before fork( )
- After fork( )
- After exec( )
- One process still contains the original code we
started with - Other process now has completely different code
int main() int pid fork( ) if (pid
0) exec( )
int main() int pid fork( ) if (pid
0) exec( )
int main() int pid fork( ) if (pid
0) exec( )
int main() // another program // starts
at beginning
int main() int pid fork( ) if (pid
0) exec( )
33Another example with exec
- Consider the print routine shown below
- Prints a number N times
- include ltiostreamgt
- include ltstdlib.hgt
- int main(int argc, char argv )
- // argv0 is the program name
- int num atoi(argv1)
- int loops atoi(argv2)
- for (int a0 altloops a)
- cout ltlt num ltlt " "
- Use print in this code
- include ltiostream.hgt
- include ltstdlib.hgt
- include ltunistd.hgt
- int main() cout ltlt "hello world" ltlt endlint
pid fork()cout ltlt PID is " ltlt pid ltlt
endlif (pid 0) - execl("./print", "print", "1", "100",
NULL)else - execl("./print", "print", "2", "100",
NULL)
34Class Exercises
- Run the example shown on the previous page
- Compile print.C (from previous slide) into an
executable print - Compile the main program and run it
- Try it printing each number
- 100 times
- 1000 times
- 10,000 times
- 100,000 times
35Creating new processes
- Lots of applications where the ability to
generate a new process comes in handy - Simple example command shell in Unix
- The shell is a C program
- Basic algorithm
- Get a command from user
- Interpret the command
- Invoke a process to execute this command
36Implementing a simple shell
- Overview
- Prompt user
- Get command
- If not time-to-exit
- Fork new process
- Replace new process with either who, ls or uptime
- Read next command
- int main() int cmd, numcout ltlt "Enter 1who,
2ls, 3uptime -gt "cin gtgt cmdwhile (cmd ! 0)
int pid fork() if (pid 0) if
(cmd1) execl("/usr/bin/who", "who",
NULL) if (cmd2) execl("/usr/bin/ls", "l
s", NULL) if (cmd3) execl("/usr/bin/uptime
", "uptime",NULL) exit(1) cin gtgt
cmd
37Class Exercises
- Implement the program shown on the previous
slide. Run it, and watch its execution. - What happens when you give an invalid number?
- Modify the program (add two more commands to the
shell we are writing), consider - date
- hostname
38Exec function
- Exec comes in many flavors (see man exec)
- We will use execl
- Specify location of new process (1st arg)
- Specify name of new process (2nd arg)
- Specify any arguments passed to new process
- Specify NULL to end parameter list (3rd arg here)
- include ltiostream.hgt
- include ltstdlib.hgt
- include ltunistd.hgt
- int main( )
- cout ltlt "hello world" ltlt endl
- int pid fork()
- coutltlt"PID is "ltltpidltltendl
- if (pid 0)
- execl("/usr/bin/ls","ls",NULL)
- else
- coutltlt"original proc"ltltendl
39What happens with exec ?
- Before fork( )
- After fork( )
- After exec( )
- One process still contains the original code we
started with - Other process now has completely different code
int main() int pid fork( ) if (pid
0) exec( )
int main() int pid fork( ) if (pid
0) exec( )
int main() int pid fork( ) if (pid
0) exec( )
int main() // another program // starts
at beginning
int main() int pid fork( ) if (pid
0) exec( )
40Creating new processes
- Lots of applications where the ability to
generate a new process comes in handy - Simple example command shell in Unix
- The shell is a C program
- Basic algorithm
- Get a command from user
- Interpret the command
- Invoke a process to execute this command
41Implementing a simple shell
- Overview
- Prompt user
- Get command
- If not time-to-exit
- Fork new process
- Replace new process with either who, ls or uptime
- Read next command
- int main() int cmd, numcout ltlt "Enter 1who,
2ls, 3uptime -gt "cin gtgt cmdwhile (cmd ! 0)
int pid fork() if (pid 0) if
(cmd1) execl("/usr/bin/who", "who",
NULL) if (cmd2) execl("/usr/bin/ls", "l
s", NULL) if (cmd3) execl("/usr/bin/uptime
", "uptime",NULL) exit(1) cin gtgt
cmd
42Class Exercises
- Implement the program shown on the previous
slide. Run it, and watch its execution. - What happens when you give an invalid number?
- Modify the program (add two more commands to the
shell we are writing), consider - date
- hostname
43Programs Processes
- We have seen how to write a program that
- When executed, could invoke additional instances
of itself (fork) - When executed, could then replace these
additional instances with other programs
replace the code in the executing process (exec) - Unix and Windows handle these basic tasks
differently
44Creating processes in Windows
- No exact Windows equivalent of fork and exec
- Windows has CreateProcess method
- Creates a new process and loads the specified
program into that process (one step) - Requires include ltwindows.hgt
- More parameters than fork exec
- Most can be NULL
- Just need to specify program to run and a few
flags
45Example using CreateProcess
- Need two variables to handle basic info must
initialize correctly - Specify the location of the new process (our
print process from last time) - Wait for it to finish
- include ltwindows.hgt
- include ltiostream.hgt
- void main( ) STARTUPINFO siPROCESS_INFORMATION
piZeroMemory( si, sizeof(si) )si.cb
sizeof(si)if ( ! CreateProcess( NULL,
..\\print\\debug\\print.exe 5 10", NULL,
NULL, TRUE, 0, NULL, NULL, si, pi) ) cerr ltlt
"CreateProcess failed." ltlt endlWaitForSingleObje
ct( pi.hProcess, INFINITE )CloseHandle(
pi.hProcess )CloseHandle( pi.hThread )
46CreateProcess syntax
- BOOL CreateProcess (
- LPCTSTR lpApplicationName, // pointer to
executable module - LPTSTR lpCommandLine, // pointer to command line
string - LPSECURITY_ATTRIBUTES lpProcessAttrib, // process
security - LPSECURITY_ATTRIBUTES lpThreadAttrib, // thread
security - BOOL bInheritHandles, // handle inheritance flag
- DWORD dwCreationFlags, // creation flags
- LPVOID lpEnvironment, // pointer to new
environment block - LPCTSTR lpCurrentDirectory, // pointer to current
dir name - LPSTARTUPINFO lpStartupInfo, // pointer to
STARTUPINFO - LPPROCESS_INFORMATION lpProcessInformation //
pointer to PROCESS_INFORMATION - )
47Comments on CreateProcess
- Can specify program in either 1st or 2nd args
- If in first, give location of program to run
- If in second, give the command line to execute
- Creation flags
- If 0, runs in existing window
- Also have other flags (combine with )
- CREATE_NEW_CONSOLE probably most useful
- Specify priority, linkage to parent, etc.
- Structures pi and si used for process
communication (how to start, basic info)
48Class Exercises
- Write a program (in the Windows VC environment)
that starts up a copy of notepad as part of its
execution - Notepad is located in c\winnt\ directory
- Dont forget to double the \ in string literal