Single-tasking Operating Systems
DOSDOS was one of the most popular single-tasking (single-user) operating systems. Some of its "features":Other notes:
Before process After process ![]()
![]()
Multi-tasking Operating Systems
UNIXUNIX Example
Operating System Concepts - 8th Edition Silberschatz, Galvin, Gagne ©2009
Details
MicrokernelsMicrokernels
Operating System Concepts - 8th Edition Silberschatz, Galvin, Gagne ©2009
![]() |
Operating System Concepts - 8th Edition Silberschatz, Galvin, Gagne ©2009 |
http://en.wikipedia.org/wiki/File:Windows_2000_architecture.svg
Marketing Name Internal Name Date Released Build No. Windows NT 3.1 NT 3.1 July 1993 528 Windows NT 3.5 NT 3.5 September 1994 807 Windows NT 3.51 NT 3.51 May 1995 1057 Windows NT 4 NT 4.0 July 1996 1381 Windows 2000 NT 5.0 December 1999 2195 Windows XP NT 5.1 August 2001 2600 Windows Server 2003 NT 5.2 March 2003 3790 Windows Vista NT 6.0 January 2007 6000 Windows Server 2008 NT 6.0 March 2008 6001 Windows 7 NT 6.1 October 2009 7600 Windows Server 2008 R2 NT 6.1 October 2009 7600 Windows 8 NT 6.2 October 2012 9200 Windows Server 2012 NT 6.2 September 2012 9200 Windows 8.1 NT 6.3 October 2013 9600 Windows Server 2012 R2 NT 6.3 October 2013 9600 Windows 10 NT 10.0 July 29, 2015 10240 Windows Server 2016 NT 10.0 September 26, 2016 14393
Users, groups, and file privileges
drwxrwx--- 2 aaron users 4096 2011-01-14 21:57 mydir -rw-r----- 2 aaron users 844 2011-04-02 02:45 myfile -rwxr-x--- 2 aaron users 9198 2016-03-04 09:18 myprogram -rw-r--r-- 1 aaron aaron 684 2010-03-22 11:17 noshare1 -rw------- 1 aaron users 92 2011-01-30 07:36 noshare2 drwxr-xr-x 2 root users 4096 2016-10-04 20:30 share |
chmod [ugoa][+-=][rwx]Modes of Operation
#include <stdio.h> /* printf */
#include <stdlib.h> /* rand, srand */
#include <time.h> /* time */
int main(void)
{
srand(time(0));
while (1)
{
int x = 0;
x = *(&x + rand()); /* line 11 */
printf("%i\n", x);
}
return 0;
}
$ gcc -ansi -pedantic -Wall -Wextra -g fault1.c $ ./a.out Segmentation fault
$ valgrind -q --tool=memcheck ./a.out ==27396== Invalid read of size 4 ==27396== at 0x4005FA: main (fault1.c:11) ==27396== Address 0x9fc5a981c is not stack'd, malloc'd or (recently) free'd ==27396== ==27396== ==27396== Process terminating with default action of signal 11 (SIGSEGV) ==27396== Access not within mapped region at address 0x9FC5A981C ==27396== at 0x4005FA: main (fault1.c:11) ==27396== If you believe this happened as a result of a stack ==27396== overflow in your program's main thread (unlikely but ==27396== possible), you can try to increase the size of the ==27396== main thread stack using the --main-stacksize= flag. ==27396== The main thread stack size used in this run was 8388608. Segmentation fault
#include <stdio.h> /* printf */
int main(void)
{
int count = 1;
while (1)
{
char x = 0;
x = *(&x + count);
printf("%i, %p\n", count, &x + count);
count++;
}
return 0;
}
$ gcc -ansi -pedantic -Wall -Wextra -g fault2.c $ ./a.out [ thousands of lines deleted ] 6250, 0x7fffea6a6ff9 6251, 0x7fffea6a6ffa 6252, 0x7fffea6a6ffb 6253, 0x7fffea6a6ffc 6254, 0x7fffea6a6ffd 6255, 0x7fffea6a6ffe 6256, 0x7fffea6a6fff Segmentation fault
0x7fffea6a7000and is on a 4K boundary (0x1000 is 4096 decimal), which is the typical size of memory pages. (More on memory pages later.)
int main(void) { while (1) ; return 0; }
PROCESS STATE CODES Here are the different values that the s, stat and state output specifiers (header "STAT" or "S") will display to describe the state of a process. D Uninterruptible sleep (usually IO) R Running or runnable (on run queue) S Interruptible sleep (waiting for an event to complete) T Stopped, either by a job control signal or because it is being traced. W paging (not valid since the 2.6.xx kernel) X dead (should never be seen) Z Defunct ("zombie") process, terminated but not reaped by its parent. For BSD formats and when the stat keyword is used, additional characters may be displayed: < high-priority (not nice to other users) N low-priority (nice to other users) L has pages locked into memory (for real-time and custom IO) s is a session leader l is multi-threaded (using CLONE_THREAD, like NPTL pthreads do) + is in the foreground process group
#include <stdio.h> /* printf */ int g_initialized1 = 10; /* DATA segment */ int g_initialized2 = 12; /* DATA segment */ int g_initialized3 = 14; /* DATA segment */ int g_uninitialized1; /* BSS segment */ int g_uninitialized2; /* BSS segment */ int g_uninitialized3; /* BSS segment */ int main(void) /* CODE segment */ { int local_variable = 5; /* STACK segment */ static int local_uninit_static; /* BSS segment */ static int local_init_static = 10; /* DATA segment */ printf(" Initialized1 global data is in the DATA segment = %p\n", &g_initialized1); printf(" Initialized2 global data is in the DATA segment = %p\n", &g_initialized2); printf(" Initialized3 global data is in the DATA segment = %p\n", &g_initialized3); printf("Uninitialized1 global data is in the BSS segment = %p\n", &g_uninitialized1); printf("Uninitialized2 global data is in the BSS segment = %p\n", &g_uninitialized2); printf("Uninitialized3 global data is in the BSS segment = %p\n", &g_uninitialized3); printf(" Code for main is in the CODE segment = %p\n", &main); printf(" Code for printf is in the CODE segment = %p\n", &printf); printf(" Code for scanf is in the CODE segment = %p\n", &scanf); printf(" Local non-static data is in the STACK segment = %p\n", &local_variable); printf(" Local uninit static data is in the BSS segment = %p\n", &local_uninit_static); printf(" Local init static data is in the DATA segment = %p\n", &local_init_static); return 0; }
Output:
gcc on Windows (32-bit)This BSS initialization was really apparent with the older (<= 2.2) LD (GNU linker) in Linux.
Initialized1 global data is in the DATA segment = 0x40200c Initialized2 global data is in the DATA segment = 0x402010 Initialized3 global data is in the DATA segment = 0x402014 Uninitialized1 global data is in the BSS segment = 0x404070 Uninitialized2 global data is in the BSS segment = 0x404050 Uninitialized3 global data is in the BSS segment = 0x404060 Code for main is in the CODE segment = 0x401100 Code for printf is in the CODE segment = 0x40128c Code for scanf is in the CODE segment = 0x40129c Local non-static data is in the STACK segment = 0x22ccb0 Local uninit static data is in the BSS segment = 0x404030 Local init static data is in the DATA segment = 0x402018bcc32 (32-bit)
Initialized1 global data is in the DATA segment = 0040F0C8 Initialized2 global data is in the DATA segment = 0040F0CC Initialized3 global data is in the DATA segment = 0040F0D0 Uninitialized1 global data is in the BSS segment = 00412434 Uninitialized2 global data is in the BSS segment = 00412438 Uninitialized3 global data is in the BSS segment = 0041243C Code for main is in the CODE segment = 004011EC Code for printf is in the CODE segment = 0040508C Code for scanf is in the CODE segment = 004050B0 Local non-static data is in the STACK segment = 0012FF88 Local uninit static data is in the BSS segment = 00412430 Local init static data is in the DATA segment = 0040F0D4cl 9.0 (32-bit)
Initialized1 global data is in the DATA segment = 0040D000 Initialized2 global data is in the DATA segment = 0040D004 Initialized3 global data is in the DATA segment = 0040D008 Uninitialized1 global data is in the BSS segment = 0040EDA0 Uninitialized2 global data is in the BSS segment = 0040ED9C Uninitialized3 global data is in the BSS segment = 0040ED98 Code for main is in the CODE segment = 00401000 Code for printf is in the CODE segment = 00401187 Code for scanf is in the CODE segment = 0040116E Local non-static data is in the STACK segment = 0012FF6C Local uninit static data is in the BSS segment = 0040E320 Local init static data is in the DATA segment = 0040D00Ccl 10.0 (64-bit)
Initialized1 global data is in the DATA segment = 000000013F45E000 Initialized2 global data is in the DATA segment = 000000013F45E004 Initialized3 global data is in the DATA segment = 000000013F45E008 Uninitialized1 global data is in the BSS segment = 000000013F460698 Uninitialized2 global data is in the BSS segment = 000000013F460694 Uninitialized3 global data is in the BSS segment = 000000013F460690 Code for main is in the CODE segment = 000000013F451000 Code for printf is in the CODE segment = 000000013F4511BC Code for scanf is in the CODE segment = 000000013F451188 Local non-static data is in the STACK segment = 000000000016FCC0 Local static data is in the BSS segment = 000000013F45F660 Local static data is in the DATA segment = 000000013F45E00Cgcc on Linux 64-bit (4.4.3)
Initialized1 global data is in the DATA segment = 0x601028 Initialized2 global data is in the DATA segment = 0x60102c Initialized3 global data is in the DATA segment = 0x601030 Uninitialized1 global data is in the BSS segment = 0x601050 Uninitialized2 global data is in the BSS segment = 0x60104c Uninitialized3 global data is in the BSS segment = 0x601054 Code for main is in the CODE segment = 0x400594 Code for printf is in the CODE segment = 0x400480 Code for scanf is in the CODE segment = 0x4004a0 Local non-static data is in the STACK segment = 0x7fffe7c96b3c Local uninit static data is in the BSS segment = 0x601048 Local init static data is in the DATA segment = 0x601034gcc on Linux 32-bit (3.3)
Initialized1 global data is in the DATA segment = 0x8049804 Initialized2 global data is in the DATA segment = 0x8049808 Initialized3 global data is in the DATA segment = 0x804980c Uninitialized1 global data is in the BSS segment = 0x8049920 Uninitialized2 global data is in the BSS segment = 0x804991c Uninitialized3 global data is in the BSS segment = 0x8049918 Code for main is in the CODE segment = 0x8048380 Code for printf is in the CODE segment = 0x804829c Code for scanf is in the CODE segment = 0x804827c Local non-static data is in the STACK segment = 0xbffff1e4 Local uninit static data is in the BSS segment = 0x8049914 Local init static data is in the DATA segment = 0x8049810
const int size = 1000 * 1000 * 500; #if 1 double data[size]; /* Takes 100 times longer to link than one in main */ int main() { return 0; } #else int main() { double data[size]; return 0; } #endif
Operating System API
Overview
Operating System Concepts - 8th Edition Silberschatz, Galvin, Gagne ©2009
ssize_t read(int fd, void *buf, size_t nbyte); /* prototype */ read(fd, buffer, nbytes); /* call */
Process management:
File management:
Call Description pid = fork(); Create a child process identical to the parent. pid = waitpid(pid, &statloc, options); Wait for a child to terminate. s = execve(name, argv, environp); Replace a process with another process. s = kill(pid, signal); Send a signal to a process. exit(status); Terminate a process and return status.
Directory management:
Call Description fd = open(file, mode); Opens a file for reading/writing/both, etc. s = close(fd); Closes a file. n = read(fd, buffer, nbytes); Read bytes from a file into memory. n = write(fd, buffer, nbytes); Write bytes from memory to a file.
Miscellaneous:
Call Description s = mkdir(name, mode); Create a new directory. s = rmdir(name); Removes a directory. s = chdir(name); Change to another directory. s = unlink(name); Delete an existing file.
Call Description id = getuid(); Get the id of the current user.
The strace Program
It is possible to "spy" on programs and see exactly what kinds of system calls are being made. This is trivial to do under Unix-based systems (such as Linux or Mac OS X).This program (ptime.c) simply retrieves the current system time, formats it appropriately, and then prints it out on the screen.
#include <stdio.h> /* printf */
#include <time.h> /* time, strftime, localtime */
int main(void)
{
struct tm *pt;
char buf[256];
time_t now;
/* Get the current system time (number of seconds since January 1, 1970) */
now = time(NULL);
/* Format and print, Weekday, Month Day, Year HH:MM:SS AM/PM Timezone */
/* example: Tuesday, May 24, 2011 5:23:36 PM PST */
pt = localtime(&now);
strftime(buf, sizeof(buf), "%A, %B %d, %Y %I:%M:%S %p %Z", pt);
printf("%s\n", buf);
return 0;
}
The exact format is compiler/library dependent. Here is what it looks like from three different compilers:
GNU gcc:
Microsoft:Tuesday, May 24, 2011 06:01:15 PM PST
Borland:Tuesday, May 24, 2011 06:01:25 PM Pacific Standard Time
Let's spy on the program and see what's going on behind-the-scenes. Assuming that the name of the executable is ptime, we run strace on the program like this (under Linux):Tuesday, May 24, 2011 06:01:35 PM
or piping stderr through less:strace ./ptime > /dev/null
and this is the output we see (errno and values)strace ./ptime 2>&1 > /dev/null | less
execve("./ptime", ["./ptime"], [/* 58 vars */]) = 0 brk(0) = 0x8051000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb785d000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=94651, ...}) = 0 mmap2(NULL, 94651, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7845000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/tls/i686/cmov/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0000m\1\0004\0\0\0"..., 512) = 512 fstat64(3, {st_mode=S_IFREG|0755, st_size=1405508, ...}) = 0 mmap2(NULL, 1415592, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x194000 mprotect(0x2e7000, 4096, PROT_NONE) = 0 mmap2(0x2e8000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x153) = 0x2e8000 mmap2(0x2eb000, 10664, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x2eb000 close(3) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7844000 set_thread_area({entry_number:-1 -> 6, base_addr:0xb78446c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 mprotect(0x2e8000, 8192, PROT_READ) = 0 mprotect(0x8049000, 4096, PROT_READ) = 0 mprotect(0x192000, 4096, PROT_READ) = 0 munmap(0xb7845000, 94651) = 0 brk(0) = 0x8051000 brk(0x8072000) = 0x8072000 open("/etc/localtime", O_RDONLY) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=2819, ...}) = 0 fstat64(3, {st_mode=S_IFREG|0644, st_size=2819, ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb785c000 read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0\0"..., 4096) = 2819 _llseek(3, -24, [2795], SEEK_CUR) = 0 read(3, "\nPST8PDT,M3.2.0,M11.1.0\n", 4096) = 24 close(3) = 0 munmap(0xb785c000, 4096) = 0 fstat64(1, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0 ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbf8804b0) = -1 ENOTTY (Inappropriate ioctl for device) mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb785c000 write(1, "Tuesday, May 29, 2012 03:08:13 P"..., 38) = 38 exit_group(0) = ?
Some other useful options:
See the man page for strace for all of the options and details.
Option Meaning -c Only display summary information. -i Displays instruction pointer with each call. -r Displays relative timestamp (microseconds). -t Show time of day of each call. -tt Show time of day with microseconds for each call. -v Verbose. Show all parameters to system calls. -x Show non-ASCII in hex. -y Include filename with file descriptor. -a column Align return values on a specific column. -e trace=set Only show calls in set (.e.g trace=open,close).
A glimpse at the relations ship between FILE * and file handles:
The FILE structure from GNU's compiler (version 4.4.3):
The FILE structure from Microsoft's compiler (version 9.0):struct _IO_FILE { int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ /* The following pointers correspond to the C++ streambuf protocol. */ /* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */ char* _IO_read_ptr; /* Current read pointer */ char* _IO_read_end; /* End of get area. */ char* _IO_read_base; /* Start of putback+get area. */ char* _IO_write_base; /* Start of put area. */ char* _IO_write_ptr; /* Current put pointer. */ char* _IO_write_end; /* End of put area. */ char* _IO_buf_base; /* Start of reserve area. */ char* _IO_buf_end; /* End of reserve area. */ struct _IO_marker *_markers; struct _IO_FILE *_chain; int _fileno; int _flags2; /* other fields removed */ }; typedef struct _IO_FILE FILE;
Also from Microsoft's header file:struct _iobuf { char *_ptr; int _cnt; char *_base; int _flag; int _file; int _charbuf; int _bufsiz; char *_tmpfname; }; typedef struct _iobuf FILE;
Incidentally, there is also a program called ltrace which traces library calls (user mode). Run it the same way:#define stdin (&__iob_func()[0]) #define stdout (&__iob_func()[1]) #define stderr (&__iob_func()[2])
and this is the output we see: (Use -n X to indent calls, where X is the column to align at. The -S option shows system calls as well.)ltrace -n 2 ./ptime > /dev/null
That's strange, where is the call to printf?
__libc_start_main(0x80484c4, 1, 0xbfd944c4, 0x8048550, 0x80485c0time(NULL) = 1338329347 localtime(0xbfd94314) = 0x006fc720 strftime("Tuesday, May 29, 2012 03:09:07 P"..., 256, "%A, %B %d, %Y %I:%M:%S %p %Z", 0x006fc720) = 37 puts("Tuesday, May 29, 2012 03:09:07 P"...) = 38 +++ exited (status 0) +++
This is a simple program (copy-read.c) that makes an exact copy of a file. It works like the copy command in Windows or the cp command in Linux. This program makes system calls to open, read, write, and close the files.
#include <stdio.h> /* printf, perror */
#include <fcntl.h> /* O_RDONLY, O_WRONLY, O_CREAT, O_TRUNC */
#include <unistd.h> /* open, close, read, write */
#define BUFSIZE 64
int main(int argc, char **argv)
{
if (argc < 3)
{
printf("usage: copy {source} {destination}\n");
return -1;
}
else
{
char *source = argv[1];
char *destination = argv[2];
int infile, outfile;
/* open source file */
infile = open(source, O_RDONLY);
if (infile == -1)
{
printf("Can't open %s for read\n", source);
return -2;
}
/* open destination file */
outfile = open(destination, O_WRONLY | O_CREAT | O_TRUNC);
if (outfile == -1)
{
printf("Can't open %s for write\n", destination);
perror(destination);
close(infile);
return -3;
}
/* copy BUFSIZE bytes from source to destination */
while (1)
{
unsigned char bytes[BUFSIZE];
int count = read(infile, bytes, BUFSIZE);
if (count > 0)
write(outfile, bytes, count);
else
{
if (count == -1)
perror(destination);
break;
}
}
close(infile);
close(outfile);
return 0;
}
}
The larger the buffer, the more efficient the program is. These are the times (using the time command) when
copying a 140 MB file. The buffer size ranged from 1 byte to 1 MB.
Here's the same program (copy-fread.c) using the C library functions fopen, fread, fwrite, and fclose. These library functions call the system functions.
1 2 4 8 16 32 64 real 3m2.412s user 0m7.690s sys 2m54.640s real 1m30.840s user 0m3.660s sys 1m27.150s real 0m48.064s user 0m2.050s sys 0m45.970s real 0m22.997s user 0m1.100s sys 0m21.860s real 0m11.541s user 0m0.630s sys 0m10.920s real 0m5.995s user 0m0.190s sys 0m5.800s real 0m2.998s user 0m0.150s sys 0m2.830s
128 256 512 1024 64K 1M real 0m1.596s user 0m0.090s sys 0m1.500s real 0m0.935s user 0m0.010s sys 0m0.910s real 0m0.533s user 0m0.010s sys 0m0.520s real 0m0.375s user 0m0.000s sys 0m0.370s real 0m0.212s user 0m0.000s sys 0m0.210s real 0m0.202s user 0m0.000s sys 0m0.200s
#include <stdio.h> /* printf, fopen, fread, fwrite, fclose */
#define BUFSIZE 1
int main(int argc, char **argv)
{
if (argc < 3)
{
printf("usage: copy {source} {destination}\n");
return -1;
}
else
{
char *source = argv[1];
char *destination = argv[2];
FILE *infile, *outfile;
/* open source file */
infile = fopen(source, "rb");
if (!infile)
{
printf("Can't open %s for read\n", source);
return -2;
}
/* open destination file */
outfile = fopen(destination, "wb");
if (!outfile)
{
printf("Can't open %s for write\n", destination);
fclose(infile);
return -3;
}
/* copy BUFSIZE bytes at a time from source to destination */
while (!feof(infile))
{
unsigned char byte[BUFSIZE];
int count = fread(byte, sizeof(unsigned char), BUFSIZE, infile);
if (count)
fwrite(byte, sizeof(unsigned char), count, outfile);
else
break;
}
fclose(infile);
fclose(outfile);
}
}
Looking at the times, there is obviously something very different between the two methods.
Library calls (fopen, fread, etc.)
System calls (open, read, etc.)
1 2 4 8 16 32 64 128 256 512 1024 512K real 0m6.930s user 0m6.480s sys 0m0.400s real 0m3.658s user 0m3.280s sys 0m0.280s real 0m2.086s user 0m1.660s sys 0m0.410s real 0m1.374s user 0m1.010s sys 0m0.360s real 0m0.735s user 0m0.450s sys 0m0.280s real 0m0.568s user 0m0.300s sys 0m0.270s real 0m0.445s user 0m0.110s sys 0m0.330s real 0m0.383s user 0m0.110s sys 0m0.270s real 0m0.348s user 0m0.050s sys 0m0.290s real 0m0.205s user 0m0.000s sys 0m0.200s
Other traces:
1 2 4 8 16 32 64 128 256 512 1024 64K 1M real 3m2.412s user 0m7.690s sys 2m54.640s real 1m30.840s user 0m3.660s sys 1m27.150s real 0m48.064s user 0m2.050s sys 0m45.970s real 0m22.997s user 0m1.100s sys 0m21.860s real 0m11.541s user 0m0.630s sys 0m10.920s real 0m5.995s user 0m0.190s sys 0m5.800s real 0m2.998s user 0m0.150s sys 0m2.830s real 0m1.596s user 0m0.090s sys 0m1.500s real 0m0.935s user 0m0.010s sys 0m0.910s real 0m0.533s user 0m0.010s sys 0m0.520s real 0m0.375s user 0m0.000s sys 0m0.370s real 0m0.212s user 0m0.000s sys 0m0.210s real 0m0.202s user 0m0.000s sys 0m0.200s
Try it with other programs:
More information on these programs:strace ls strace ls -l strace cp
C code: (rw.c) Recall this diagram
#include <stdio.h> /* read, write */
#define BUFSIZE 1
int main(void)
{
/* copy BUFSIZE bytes at a time from stdin to stdout */
while (1)
{
unsigned char bytes[BUFSIZE];
int count = read(0, bytes, BUFSIZE);
if (count > 0)
write(1, bytes, count);
else
{
if (count == -1)
perror("Read failed");
break;
}
}
return 0;
}
Assembly: (readwrite.asm)
; readwrite < textfile
;
; Build using these commands:
; nasm -f elf64 -g -F dwarf readwrite.asm
; ld -o readwrite readwrite.o
;
SECTION .bss
BUFSIZE equ 64 ; how many bytes to read each time
Buffer: resb BUFSIZE ; buffer to read into
SECTION .data
SECTION .text
global _start
; Read from stdin
; eax - SYS_read (3)
; ebx - file descriptor (0 - stdin)
; ecx - buffer to write into
; edx - number of bytes to read
_start: mov eax,3 ; SYS_read
mov ebx,0 ; stdin is 0
mov ecx,Buffer ; address of Buffer
mov edx,BUFSIZE ; number of bytes to read
int 80h ; make system call (traps to kernel)
mov esi,eax ; eax contains actual number of bytes read (save for later)
cmp eax,0 ; if eax is 0 then the end of file was reached
je Exit ; and we will exit the program
; Write to stdout
; eax - SYS_write (4)
; ebx - file descriptor (1 - stdout)
; ecx - buffer to read from
; edx - number of bytes to write
mov eax,4 ; SYS_write
mov ebx,1 ; stdout is 1
mov ecx,Buffer ; address of Buffer
mov edx,esi ; how many bytes to write (how many were read)
int 80h ; make system call (traps to kernel)
jmp _start ; read more bytes
; Exit the program
Exit:
mov eax,1 ; SYS_exit
mov ebx,0 ; return value (to OS)
int 80H ; make system call
The relevant system calls:
The system calls are defined in unistd.h and syscall.h#define __NR_exit 1 #define __NR_read 3 #define __NR_write 4 #define SYS_exit __NR_exit #define SYS_read __NR_read #define SYS_write __NR_write
The Win32 API
UNIX/POSIX Windows Description fork CreateProcess Creates a new process. waitpid WaitForSingleObject Waits for a process to exit. execve (none) CreateProcess = fork + execve exit ExitProcess Terminate execution. open CreateFile Create a new file or open an existing one. close CloseHandle Closes a file read ReadFile Read data from a file. write WriteFile Write data to a file. lseek SetFilePointer Moves the file pointer. stat GetFileAttributes Get attributes from a file. mkdir CreateDirectory Creates a new directory. rmdir RemoveDirectory Removes a directory. unlink DeleteFile Deletes an existing file. chdir SetCurrentDirectory Change the current working directory. time GetLocalTime Get the current system time.