The document discusses UNIX system calls. It describes that system calls are functions used in the kernel to request the operating system perform an action on behalf of a user program. To the programmer, system calls appear as normal C function calls. However, they require changing the process execution mode to kernel mode. Common system calls allow processes to manage files, control other processes, and provide inter-process communication.
This document discusses how to add a system call to the Ubuntu operating system. It begins with an introduction to Ubuntu and explains what a kernel and system calls are. It then provides step-by-step instructions for adding a new system call, including editing relevant files, adding code, and recompiling the kernel. Sample code for calling the new system call is also included. The document concludes with instructions for replacing the current kernel with a new one that has been compiled.
The document provides information about various Unix commands including:
- The type command is used to determine if a command is internal or external. Internal commands are built into the shell while external commands are located in directories like /bin.
- The man command displays online manual pages for commands and provides details on usage, options, and examples. It can be used with options like -f to show what section a command is in or -k to search manuals.
- The whatis command displays a one-line description of commands from their manual pages.
- Commands like who, users, whoami display information about the logged in user like username, terminal, and login time. The last command shows login history
Chapter 1 Introduction to Operating System ConceptsMeenalJabde
The document provides an overview of operating systems including:
- The definition of an operating system as a program that controls hardware and acts as an interface between users and computers.
- The key functions of operating systems including providing convenience, efficiency, and ability to evolve.
- Concepts such as processes, process states, process control blocks, and system calls. It describes what they are and their purpose.
- A brief history of operating systems from first to fourth generation systems.
- The main types of operating systems including batch, time-sharing, distributed, network, and real-time operating systems.
- Common services offered by most operating systems such as user interface, program execution, file
Chapter 2 Introduction to Unix ConceptsMeenalJabde
The document provides an introduction to Unix concepts including:
1. It describes the architecture of Unix as having 4 layers - hardware, kernel, shell commands, and application layer. The kernel interacts with hardware and manages tasks like memory and process scheduling.
2. It lists some basic Unix commands like ls, echo, printf, who, date, passwd, cal and explains how to combine commands using operators like && and ||.
3. It explains Unix files and directories are organized in a hierarchical tree structure with the root directory at the top. There are different types of files like ordinary, special, pipes and symbolic links.
This is the presentation of our journal-first paper which was presented at ICSE 2018. The pre-print of the paper can be found at https://www.researchgate.net/publication/319687129_Analyzing_a_Decade_of_Linux_System_Calls
Unix uses processes to run programs and operating system functions. There are two types of processes - system processes which execute OS code and user processes which execute user programs. Processes can be in different states like running, ready, blocked etc. The kernel manages processes using data structures like process table entry and user area. Important process management operations include forking to create new processes, wait/exit for process termination, and signals for inter-process communication.
This document discusses system calls in Linux. It defines system calls as service points for user programs to request services from the kernel. There are about 300 system calls in Linux, listed in /usr/include/asm/unistd.h. A system call executes in kernel space unlike a library function, and involves packaging arguments, transferring control to the kernel via a trap, and returning control back with a return value. The strace command can be used to trace system calls made by a program. Hands-on examples are provided to demonstrate system calls versus library functions.
VTU 3RD SEM UNIX AND SHELL PROGRAMMING SOLVED PAPERSvtunotesbysree
This document contains information about a UNIX and Shell Programming exam, including:
- The exam is for a 4th semester BE degree and covers UNIX and Shell Programming topics.
- It has two parts (A and B) and students must answer 5 full questions selecting at least 2 from each part.
- Part 1 covers topics like UNIX architecture, parent-child relationships, file systems, and file permissions.
- Part 2 covers topics like grep commands, sed editing, regular expressions, shell features, AWK and Perl programming.
This document discusses how to add a system call to the Ubuntu operating system. It begins with an introduction to Ubuntu and explains what a kernel and system calls are. It then provides step-by-step instructions for adding a new system call, including editing relevant files, adding code, and recompiling the kernel. Sample code for calling the new system call is also included. The document concludes with instructions for replacing the current kernel with a new one that has been compiled.
The document provides information about various Unix commands including:
- The type command is used to determine if a command is internal or external. Internal commands are built into the shell while external commands are located in directories like /bin.
- The man command displays online manual pages for commands and provides details on usage, options, and examples. It can be used with options like -f to show what section a command is in or -k to search manuals.
- The whatis command displays a one-line description of commands from their manual pages.
- Commands like who, users, whoami display information about the logged in user like username, terminal, and login time. The last command shows login history
Chapter 1 Introduction to Operating System ConceptsMeenalJabde
The document provides an overview of operating systems including:
- The definition of an operating system as a program that controls hardware and acts as an interface between users and computers.
- The key functions of operating systems including providing convenience, efficiency, and ability to evolve.
- Concepts such as processes, process states, process control blocks, and system calls. It describes what they are and their purpose.
- A brief history of operating systems from first to fourth generation systems.
- The main types of operating systems including batch, time-sharing, distributed, network, and real-time operating systems.
- Common services offered by most operating systems such as user interface, program execution, file
Chapter 2 Introduction to Unix ConceptsMeenalJabde
The document provides an introduction to Unix concepts including:
1. It describes the architecture of Unix as having 4 layers - hardware, kernel, shell commands, and application layer. The kernel interacts with hardware and manages tasks like memory and process scheduling.
2. It lists some basic Unix commands like ls, echo, printf, who, date, passwd, cal and explains how to combine commands using operators like && and ||.
3. It explains Unix files and directories are organized in a hierarchical tree structure with the root directory at the top. There are different types of files like ordinary, special, pipes and symbolic links.
This is the presentation of our journal-first paper which was presented at ICSE 2018. The pre-print of the paper can be found at https://www.researchgate.net/publication/319687129_Analyzing_a_Decade_of_Linux_System_Calls
Unix uses processes to run programs and operating system functions. There are two types of processes - system processes which execute OS code and user processes which execute user programs. Processes can be in different states like running, ready, blocked etc. The kernel manages processes using data structures like process table entry and user area. Important process management operations include forking to create new processes, wait/exit for process termination, and signals for inter-process communication.
This document discusses system calls in Linux. It defines system calls as service points for user programs to request services from the kernel. There are about 300 system calls in Linux, listed in /usr/include/asm/unistd.h. A system call executes in kernel space unlike a library function, and involves packaging arguments, transferring control to the kernel via a trap, and returning control back with a return value. The strace command can be used to trace system calls made by a program. Hands-on examples are provided to demonstrate system calls versus library functions.
VTU 3RD SEM UNIX AND SHELL PROGRAMMING SOLVED PAPERSvtunotesbysree
This document contains information about a UNIX and Shell Programming exam, including:
- The exam is for a 4th semester BE degree and covers UNIX and Shell Programming topics.
- It has two parts (A and B) and students must answer 5 full questions selecting at least 2 from each part.
- Part 1 covers topics like UNIX architecture, parent-child relationships, file systems, and file permissions.
- Part 2 covers topics like grep commands, sed editing, regular expressions, shell features, AWK and Perl programming.
The document discusses Linux runlevels, changing runlevels, and shutting down or rebooting a Linux system. It covers:
- Linux systems support runlevels 0-6, with levels 0, 1, 6 having specific purposes like halt, single-user mode, reboot. Levels 2-5 are for multi-user modes.
- The default runlevel is set in /etc/inittab and runlevel scripts are located in /etc/rc.d/rc?.d. The telinit command or changing the kernel command line can change runlevels.
- Clean shutdown is done with the shutdown command, which alerts users, signals processes, and changes runlevels gracefully. Halt, reboot,
Part 04 Creating a System Call in LinuxTushar B Kute
Presentation on "System Call creation in Linux".
Presented at Army Institute of Technology, Pune for FDP on "Basics of Linux Kernel Programming". by Tushar B Kute (http://tusharkute.com).
Operating System ,UNIX & LINUX base System Calls
1) Process Creation
2) Executing a Command
3) Wait command
4) Sleep Command
5) Sleep Command using getpid
6) Signal Handling
With C-Programming & BASH Programming
This document discusses embedded Linux programming. It covers topics such as what Linux is, the layers in a Linux system including the kernel and user programs, how Linux differs from legacy real-time operating systems, and an agenda for a course on embedded Linux driver development that covers the Linux kernel, memory management, interrupts, and networking. It also provides information on basic Linux command line tools and file permissions.
The document discusses system calls in Linux. It defines system calls as service points for user programs to request services from the kernel. It describes how system calls provide an abstracted hardware interface, ensure security and stability, and make process management easier. The document contrasts system calls with library functions, noting that system calls execute in kernel space with special privileges while library functions are ordinary user space functions. It also covers how system calls are implemented and executed via wrappers and describes tracing system calls using strace.
This document provides an overview of different Linux I/O models including blocking I/O, non-blocking I/O, I/O multiplexing using select, poll, epoll, signal-driven I/O and asynchronous I/O. It describes key functions and system calls used for each model and provides examples of how they can be used in drivers and applications.
The document discusses operating system concepts like processor modes, system calls, inter-process communication (IPC), process creation, and linking and loading of processes. It defines an operating system as an interface between the user and computer hardware that manages system resources efficiently. It explains that the CPU has two modes - kernel mode and user mode - to distinguish between system and user code. System calls allow user programs to request services from the operating system by triggering an interrupt to switch to kernel mode. Common IPC mechanisms and their related system calls are also outlined.
This document discusses Unix system calls and standard I/O functions in C. It begins by defining system calls as requests to the operating system for services, typically made via traps into the kernel. It then covers various system calls for process control, file manipulation, directory manipulation, memory allocation, and I/O. It also discusses standard I/O functions in the C standard library that provide higher-level abstraction over system calls for file I/O.
This document discusses various inter-process communication (IPC) mechanisms in Linux, including pipes, FIFOs, and message queues. Pipes allow one-way communication between related processes, while FIFOs (named pipes) allow communication between unrelated processes through named pipes that persist unlike anonymous pipes. Message queues provide more robust messaging between unrelated processes by allowing messages to be queued until received and optionally retrieved out-of-order or by message type. The document covers the key functions and system calls for creating and using each IPC mechanism in both shell and C programming.
Writing Character driver (loadable module) in linuxRajKumar Rampelli
It covers the step by step approach on how to write a simple loadable character device driver in linux. What are Device files in linux detail. How user application interact with character driver using a device file.
This document outlines the topics to be covered in a shell scripting workshop, including shells and shell scripting, Bash commands and scripting, Linux commands, file permissions, input/output redirection, regular expressions, automation, and testing. It provides an overview of shells like Bash, Bourne shell, and C shell. It also describes various Linux directories and files, file commands, user commands, and help commands.
Fork() is a system call that creates a new process by duplicating the calling process. The child process created by fork() is an exact duplicate of the parent process, having the same memory space and file descriptors. Exec() is another system call that replaces the current process with a new executable, keeping the same process ID. It is commonly used along with fork() to launch new programs from within a process. Fork() alone does not replace the process image - it is used to create a new process while exec() replaces the current process image with a new program.
This document discusses processes in Linux. It defines a process as a running instance of a program in memory that is allocated space for variables and instructions. All processes are descended from the systemd process. It describes process states like running, sleeping, stopped, and zombie. It also discusses process monitoring and management tools like top, ps, kill, and setting process priorities with nice and renice. Examples are provided on using ps to view specific processes by user, name, ID, parent ID, and customize the output.
This document discusses the key differences between ANSI C and K&R C. It covers four main points: 1) Function prototyping in ANSI C allows compilers to check for invalid function calls, unlike in K&R C. 2) ANSI C supports the const and volatile qualifiers. 3) ANSI C supports internationalization with wide characters and setlocale. 4) ANSI C allows function pointers to be used without dereferencing. The document provides examples to illustrate each point.
This document discusses threads and threading in Linux. It begins with an overview of threads, their similarities and differences to processes, and how they are implemented in Linux using the Native POSIX Threads Library (NPTL). It then covers key pthreads APIs for thread management, including thread creation, termination, joining threads, attributes, cancellation, and thread-specific data. The document provides code examples to demonstrate the use of various pthreads functions.
The document discusses Linux process and scheduling concepts. It describes the key data structures used to represent processes like task_struct and thread_info. It covers process states, creation via fork(), exec(), and termination. Scheduling policies like CFS and priorities are explained. Core scheduling functions like schedule() and how runqueues and load weights work are summarized.
The document discusses the boot sequence of a computer system. It examines each step including the PROM monitor, boot block, secondary boot loader, and OS kernel initialization. It also covers modifying the boot process, selecting alternate boot devices, different boot loaders, and proper system shutdown procedures.
This document provides an introduction to the Lisp programming language. It discusses Lisp's origins and design, current implementations, why it was conceived, its core data structures and operations, control structures, recursion features, input/output functions, and loading/compiling files. Examples are provided to demonstrate various language concepts like recursion, set operations, and functional programming with lists.
The document provides an overview of the initialization process in the Linux kernel from start_kernel to rest_init. It lists the functions called during this process organized by category including functions for initialization of multiprocessor support (SMP), memory management (MM), scheduling, timers, interrupts, and architecture specific setup. The setup_arch section focuses on x86 architecture specific initialization functions such as reserving memory regions, parsing boot parameters, initializing memory mapping and MTRRs.
This document provides an introduction to Linux, including definitions of open source software and its advantages. It discusses the Linux system overview consisting of the kernel, OS services, and applications. It also covers Linux usage basics such as directories, shells, files, users, permissions, and input/output redirection. The document is intended to explain what topics will be covered in an introduction to Linux workshop.
This presentation covers the understanding of system calls for various resource management and covers system calls for file management in details. The understanding of using system calls helps to start with working with device driver programming on Unix/Linux OS.
This presentation discusses system calls and provides an overview of their key aspects:
System calls provide an interface between processes and the operating system. They allow programs to request services from the OS like reading/writing files. There are different methods of passing parameters to the OS, such as via registers, parameter blocks, or pushing to the stack. System calls fall into categories including process control, file management, device management, information maintenance, and communication. An example is given of how system calls would be used in a program to copy data between two files.
The document discusses Linux runlevels, changing runlevels, and shutting down or rebooting a Linux system. It covers:
- Linux systems support runlevels 0-6, with levels 0, 1, 6 having specific purposes like halt, single-user mode, reboot. Levels 2-5 are for multi-user modes.
- The default runlevel is set in /etc/inittab and runlevel scripts are located in /etc/rc.d/rc?.d. The telinit command or changing the kernel command line can change runlevels.
- Clean shutdown is done with the shutdown command, which alerts users, signals processes, and changes runlevels gracefully. Halt, reboot,
Part 04 Creating a System Call in LinuxTushar B Kute
Presentation on "System Call creation in Linux".
Presented at Army Institute of Technology, Pune for FDP on "Basics of Linux Kernel Programming". by Tushar B Kute (http://tusharkute.com).
Operating System ,UNIX & LINUX base System Calls
1) Process Creation
2) Executing a Command
3) Wait command
4) Sleep Command
5) Sleep Command using getpid
6) Signal Handling
With C-Programming & BASH Programming
This document discusses embedded Linux programming. It covers topics such as what Linux is, the layers in a Linux system including the kernel and user programs, how Linux differs from legacy real-time operating systems, and an agenda for a course on embedded Linux driver development that covers the Linux kernel, memory management, interrupts, and networking. It also provides information on basic Linux command line tools and file permissions.
The document discusses system calls in Linux. It defines system calls as service points for user programs to request services from the kernel. It describes how system calls provide an abstracted hardware interface, ensure security and stability, and make process management easier. The document contrasts system calls with library functions, noting that system calls execute in kernel space with special privileges while library functions are ordinary user space functions. It also covers how system calls are implemented and executed via wrappers and describes tracing system calls using strace.
This document provides an overview of different Linux I/O models including blocking I/O, non-blocking I/O, I/O multiplexing using select, poll, epoll, signal-driven I/O and asynchronous I/O. It describes key functions and system calls used for each model and provides examples of how they can be used in drivers and applications.
The document discusses operating system concepts like processor modes, system calls, inter-process communication (IPC), process creation, and linking and loading of processes. It defines an operating system as an interface between the user and computer hardware that manages system resources efficiently. It explains that the CPU has two modes - kernel mode and user mode - to distinguish between system and user code. System calls allow user programs to request services from the operating system by triggering an interrupt to switch to kernel mode. Common IPC mechanisms and their related system calls are also outlined.
This document discusses Unix system calls and standard I/O functions in C. It begins by defining system calls as requests to the operating system for services, typically made via traps into the kernel. It then covers various system calls for process control, file manipulation, directory manipulation, memory allocation, and I/O. It also discusses standard I/O functions in the C standard library that provide higher-level abstraction over system calls for file I/O.
This document discusses various inter-process communication (IPC) mechanisms in Linux, including pipes, FIFOs, and message queues. Pipes allow one-way communication between related processes, while FIFOs (named pipes) allow communication between unrelated processes through named pipes that persist unlike anonymous pipes. Message queues provide more robust messaging between unrelated processes by allowing messages to be queued until received and optionally retrieved out-of-order or by message type. The document covers the key functions and system calls for creating and using each IPC mechanism in both shell and C programming.
Writing Character driver (loadable module) in linuxRajKumar Rampelli
It covers the step by step approach on how to write a simple loadable character device driver in linux. What are Device files in linux detail. How user application interact with character driver using a device file.
This document outlines the topics to be covered in a shell scripting workshop, including shells and shell scripting, Bash commands and scripting, Linux commands, file permissions, input/output redirection, regular expressions, automation, and testing. It provides an overview of shells like Bash, Bourne shell, and C shell. It also describes various Linux directories and files, file commands, user commands, and help commands.
Fork() is a system call that creates a new process by duplicating the calling process. The child process created by fork() is an exact duplicate of the parent process, having the same memory space and file descriptors. Exec() is another system call that replaces the current process with a new executable, keeping the same process ID. It is commonly used along with fork() to launch new programs from within a process. Fork() alone does not replace the process image - it is used to create a new process while exec() replaces the current process image with a new program.
This document discusses processes in Linux. It defines a process as a running instance of a program in memory that is allocated space for variables and instructions. All processes are descended from the systemd process. It describes process states like running, sleeping, stopped, and zombie. It also discusses process monitoring and management tools like top, ps, kill, and setting process priorities with nice and renice. Examples are provided on using ps to view specific processes by user, name, ID, parent ID, and customize the output.
This document discusses the key differences between ANSI C and K&R C. It covers four main points: 1) Function prototyping in ANSI C allows compilers to check for invalid function calls, unlike in K&R C. 2) ANSI C supports the const and volatile qualifiers. 3) ANSI C supports internationalization with wide characters and setlocale. 4) ANSI C allows function pointers to be used without dereferencing. The document provides examples to illustrate each point.
This document discusses threads and threading in Linux. It begins with an overview of threads, their similarities and differences to processes, and how they are implemented in Linux using the Native POSIX Threads Library (NPTL). It then covers key pthreads APIs for thread management, including thread creation, termination, joining threads, attributes, cancellation, and thread-specific data. The document provides code examples to demonstrate the use of various pthreads functions.
The document discusses Linux process and scheduling concepts. It describes the key data structures used to represent processes like task_struct and thread_info. It covers process states, creation via fork(), exec(), and termination. Scheduling policies like CFS and priorities are explained. Core scheduling functions like schedule() and how runqueues and load weights work are summarized.
The document discusses the boot sequence of a computer system. It examines each step including the PROM monitor, boot block, secondary boot loader, and OS kernel initialization. It also covers modifying the boot process, selecting alternate boot devices, different boot loaders, and proper system shutdown procedures.
This document provides an introduction to the Lisp programming language. It discusses Lisp's origins and design, current implementations, why it was conceived, its core data structures and operations, control structures, recursion features, input/output functions, and loading/compiling files. Examples are provided to demonstrate various language concepts like recursion, set operations, and functional programming with lists.
The document provides an overview of the initialization process in the Linux kernel from start_kernel to rest_init. It lists the functions called during this process organized by category including functions for initialization of multiprocessor support (SMP), memory management (MM), scheduling, timers, interrupts, and architecture specific setup. The setup_arch section focuses on x86 architecture specific initialization functions such as reserving memory regions, parsing boot parameters, initializing memory mapping and MTRRs.
This document provides an introduction to Linux, including definitions of open source software and its advantages. It discusses the Linux system overview consisting of the kernel, OS services, and applications. It also covers Linux usage basics such as directories, shells, files, users, permissions, and input/output redirection. The document is intended to explain what topics will be covered in an introduction to Linux workshop.
This presentation covers the understanding of system calls for various resource management and covers system calls for file management in details. The understanding of using system calls helps to start with working with device driver programming on Unix/Linux OS.
This presentation discusses system calls and provides an overview of their key aspects:
System calls provide an interface between processes and the operating system. They allow programs to request services from the OS like reading/writing files. There are different methods of passing parameters to the OS, such as via registers, parameter blocks, or pushing to the stack. System calls fall into categories including process control, file management, device management, information maintenance, and communication. An example is given of how system calls would be used in a program to copy data between two files.
System calls provide an interface between processes and the operating system. They allow programs to request services like reading/writing files or communicating over a network. Common system calls include opening/closing files, reading/writing data, process creation/termination, and requesting the current time/date. System calls are grouped into categories like process control, file management, device management, information maintenance, and communications.
The document discusses application program interfaces (APIs) and how they allow programmers to use operating system and hardware functions without needing to know all the technical details. It provides an example of a programmer using an API call to create a file, with the operating system then handling the disk queries, file system entry creation, and hardware-specific operations behind the scenes. APIs have become important in the software industry as controlling a popular API can influence what programs are written and provide revenue opportunities.
Operating Systems 1 (6/12) - ProcessesPeter Tröger
The document discusses operating system concepts related to processes. It covers:
1) The core operating system task of managing multiple running processes through techniques like multi-processing and multi-tasking.
2) A process is the unit of execution and is represented by a process control block containing its state and resource usage information.
3) Processes go through various states in their lifecycle including running, ready, blocked, and terminated as they are scheduled by the operating system dispatcher.
A fast file system for unix presentation by parang saraf (cs5204 VT)Parang Saraf
This is the presentation of the paper "A fast file system for unix"
In case if you need a copy of these slides feel free to contact me at parang[DOT]saraf[AT]gmail
This document presents methods for solving single non-linear equations and systems of non-linear equations numerically. It describes the Newton-Raphson and secant methods. The Newton-Raphson method uses iterative approximations based on the Taylor series expansion and its derivative to find roots. The secant method approximates the derivative as the difference quotient. MATLAB functions are provided to implement both methods to find roots of sample non-linear equations.
The document provides information about the bisection method for finding roots of non-linear equations. It defines the bisection method, outlines its basis and key steps, and provides an example of using the method to find the depth at which a floating ball is submerged in water. Over 10 iterations, the bisection method converges on an estimated root of 0.06241 for the example equation, with 2 significant digits found to be correct after the final iteration. The document also discusses an application of using the bisection method to find resistance of a thermistor at a given temperature.
The kernel is the central part of an operating system that manages input/output requests and translates them into instructions for the CPU and other components. It is responsible for memory management, allocating processes to the CPU, and handling input/output from devices. The basic structure of a kernel includes facilities for the CPU, computer memory, and input/output devices. Kernels can take different forms such as monolithic, micro, hybrid, nano, or exokernel depending on their modularity and how they expose hardware resources to other parts of the system.
Unix Process Management
Process management is an integral part of any modern day operating system (OS). The OS must allocate resources to processes, enable processes to share and exchange information, protect the resources of each process from other processes and enable synchronisation among processes
Linux is a free, open-source operating system based on UNIX with a modular kernel. It uses processes, threads, virtual memory, and files systems. Device drivers allow access to hardware via the block I/O system. Interprocess communication includes signals, pipes, shared memory, and semaphores. Security features authentication via PAM and access controls permissions via user and group IDs.
Ethernet is a family of local area network (LAN) protocols that was first developed in 1976. It uses bus or star topologies and supports data transfer rates of 10/100/1000 Mbps. Fast Ethernet was developed to support higher speeds of 100 Mbps, while Gigabit Ethernet supports 1000 Mbps. Ethernet uses CSMA/CD to handle simultaneous transmission demands in half-duplex mode, while full-duplex mode allows simultaneous transmission in both directions. Token ring is another common LAN protocol that uses a token passing mechanism to control access instead of CSMA/CD.
How to find the roots of Nonlinear Equations?
Newton-Raphson method is not the only way!
How about a system of nonlinear equations?
#WikiCourses
https://wikicourses.wikispaces.com/Topic+Roots+of+Nonlinear+Equations
The document discusses the history and characteristics of UNIX operating systems. It describes how UNIX was developed in the 1960s and has since evolved into many different versions. Some key aspects of UNIX include its multi-user and multi-tasking capabilities, large number of free and commercial applications, and importance in internet development. The document also covers UNIX system calls, memory management, process management, and file systems.
The infrared survey report documents an inspection of a 1990 100kVA oil-cooled transformer located at a TNB Distribution station in Muadzam Shah. The report finds:
1) Elevated temperatures of up to 35.2°C on the HV cable, indicating deterioration of the cable insulation from surface dirt and moisture. Maintenance within 6 months is recommended to remove, inspect, clean, and reinsulate the cable.
2) A hot spot of 102.3°C found on the red phase of the LV cable termination, suggesting a high resistance bad contact. Immediate shutdown and cleaning of the cable termination contact surface is recommended.
3) Additional notes to thoroughly clean and ret
1. The document discusses the major components of operating system structures including process management, main memory management, file management, I/O system management, secondary storage management, networking, protection systems, and command interpreter systems.
2. It also describes operating system services such as program execution, I/O operations, file system manipulation, communications, error detection, and resource allocation.
3. The types of system calls are outlined related to process control, file manipulation, device manipulation, information maintenance, and communication.
System Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbsashukiller7
System calls allow processes to request services from the operating system kernel. There are several categories of system calls including process control, file management, process information maintenance, and inter-process communication.
Process control system calls like fork(), exit(), and exec() allow processes to be created, terminated, and new programs to be run. File management system calls like open(), read(), write(), and close() allow processes to open, read, write to, and close files. Process information maintenance system calls like getpid(), alarm(), and sleep() allow processes to access information about themselves or other processes. Communication system calls like pipe() and shmget() allow processes to communicate with each other.
What Have Syscalls Done for you Lately?Docker, Inc.
If you've ever written any code - even just Hello World - you've used some syscalls. In this talk we'll explore what syscalls are, how they are used to set up containers, and how to make your deployment more secure at runtime by limiting the syscalls your containers can make thanks to seccomp and Linux security modules like AppArmor.
We'll also discuss how, if your architecture is broken into containerized microservices, this gives you a great opportunity to improve security by limiting what each container can do. This is where containerized microservices really shine over traditional monoliths from a security perspective - so it's helpful to know about if you're trying to convince your security team that containers are a good idea.
There will be lots of live demos!
The document discusses trap handling in Linux, focusing on system calls. It begins with background on interrupts, traps, and system calls. It then describes the function call flow from start_kernel() and initialization of the Interrupt Descriptor Table (IDT). Next, it covers system call entry and initialization of the system call table. Finally, it discusses the system call procedure from a user application using glibc and the Linux kernel. Key topics include IDT structure and gates, MSR register usage for system calls, fast vs slow system call paths, and how system calls are invoked and handled in the kernel.
The Linux kernel acts as an interface between applications and hardware, managing system resources and providing access through system calls; it uses a monolithic design where all components run in the kernel thread for high performance but can be difficult to maintain, though Linux allows dynamic loading of modules. Device drivers interface hardware like keyboards, hard disks, and network devices with the operating system, and are implemented as loadable kernel modules that are compiled using special makefiles and registered with the kernel through system calls.
The respective talk was held by Oleksandr Shevchenko (Senior Engineering Consultant, GlobalLogic) at GlobalLogic Lviv Embedded TechTalk #2 on May 23, 2018.
Oleksandr presentation is about features of software architecture, which provides parallel work of Linux and operating system real-time on different cores of a single processor. The talk is also about the Linux mechanism, which allows to connect the processor cores after the boot process has finished, the so-called "CPU Hotplug".
The document discusses system calls and provides examples of how they are used. It defines system calls as interfaces between processes and the operating system. It then covers specific system calls like open(), read(), write(), fork(), wait(), and exit() providing their syntax and discussing how they are implemented and used to copy files and create processes. It includes pseudocode examples and discusses how open() works by transferring from user to kernel space.
seccomp is a computer security facility in the Linux kernel, pledge is a similar security facility in the OpenBSD kernel. In this presentation Giovanni Bechis will review the development story and progress of both kernel interfaces and will analyze the main differences. There will be some examples of implementations of security patches made for some important open source projects.
This document discusses building a virtual platform for the OpenRISC architecture using SystemC and transaction-level modeling. It covers setting up the toolchain, writing test programs, and simulating the platform using event-driven or cycle-accurate simulation with Icarus Verilog or the Vorpsoc simulator. The virtual platform allows fast development and debugging of OpenRISC code without requiring physical hardware.
Apache Flink: API, runtime, and project roadmapKostas Tzoumas
The document provides an overview of Apache Flink, an open source stream processing framework. It discusses Flink's programming model using DataSets and transformations, real-time stream processing capabilities, windowing functions, iterative processing, and visualization tools. It also provides details on Flink's runtime architecture, including its use of pipelined and staged execution, optimizations for iterative algorithms, and how the Flink optimizer selects execution plans.
[Ruxcon 2011] Post Memory Corruption Memory AnalysisMoabi.com
The document introduces PMCMA, a debugger tool that analyzes memory corruption bugs by forcing processes to fork, overwriting memory locations in the offspring processes, and monitoring execution to map exploitable scenarios. PMCMA aims to provide a roadmap for exploitation by identifying vulnerabilities and possible exploitation techniques like truncating function pointers or exploiting 4-byte aligned memory writes. The tool is available online and has received over 10,000 downloads in its first two months.
The document discusses the basic components of a computer system including hardware such as input devices, the CPU, storage, and output devices. It also covers software components like system software, application software, and different types of computer languages. The document outlines the typical life cycle of system development from requirements analysis to design, coding, testing, and maintenance.
The document introduces Program Semantics-Aware Intrusion Detection (PAID), a host-based intrusion prevention system that uses compiler techniques to automatically generate an accurate system call policy for applications. It extracts system call sites, ordering, and arguments from source code to build a finite state automaton for checks. PAID can prevent control hijacking attacks and mimicry attacks by checking system call ordering, sites of entry, and return addresses on the stack. It incurs low performance overhead of around 5% for most applications.
Program Assignment Process ManagementObjective This program a.docxwkyra78
Program Assignment : Process Management
Objective: This program assignment is given to the Operating Systems course to allow the students to figure out how a single process (parent process) creates a child process and how they work on Unix/Linux(/Mac OS X/Windows) environment. Additionally, student should combine the code for describing inter-process communication into this assignment. Both parent and child processes interact with each other through shared memory-based communication scheme or message passing scheme.
Environment: Unix/Linux environment (VM Linux or Triton Server, or Mac OS X), Windows platform
Language: C or C++, Java
Requirements:
i. You have wide range of choices for this assignment. First, design your program to explain the basic concept of the process management in Unix Kernel. This main idea will be evolved to show your understanding on inter-process communication, file processing, etc.
ii. Refer to the following system calls:
- fork(), getpid(), family of exec(), wait(), sleep() system calls for process management
- shmget(), shmat(), shmdt(), shmctl() for shared memory support or
- msgget(), msgsnd(), msgrcv(), msgctl(), etc. for message passing support
iii. The program should present that two different processes, both parent and child, execute as they are supposed to.
iv. The output should contain the screen capture of the execution procedure of the program.
v. Interaction between parent and child processes can be provided through inter-process communication schemes, such as shared-memory or message passing schemes.
vi. Result should be organized as a document which explains the overview of your program, code, execution results, and the conclusion including justification of your program, lessons you've learned, comments, etc.
Note:
i. In addition, please try to understand how the local and global variables work across the processes
ii. read() or write () functions are used to understand how they work on the different processes.
iii. For extra credit, you can also incorporate advanced features, like socket or thread functions, into your code.
Examples:
1. Process Creation and IPC with Shared Memory Scheme
=============================================================
#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t pid;
int segment_id; //allocate the memory
char *shared_memory; //pointer to memory
const int size = 4096;
segment_id = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
shared_memory = (char *) shmat(segment_id, NULL, 0);
pid = fork();
if(pid < 0) { //error
fprintf(stderr, "Fork failed");
return 1;
}
else if(pid == 0){ //child process
char *child_shared_memory;
child_shared_memory = (char *) shmat(segment_id,NULL,0); //attach mem
sprintf(child_shared_memory, "Hello parent process!"); //write to the shared mem
shmdt(child_shared_memory);
}
else ...
The document summarizes a presentation given by Tomer Teller about the Stuxnet malware. It describes how Stuxnet infected industrial control systems by exploiting Windows vulnerabilities, spreading on removable drives, and ultimately reprogramming PLCs to sabotage Iran's nuclear program. Key infection techniques discussed include exploiting LNK and Print Spooler vulnerabilities, using autorun.inf files and rootkit techniques to propagate, and replacing DLL files to monitor and inject commands to PLCs.
This document describes user-defined table-generating functions (UDTFs) in three sentences:
UDTFs allow users to define functions that take in rows from a table and output multiple rows, providing a one-to-many mapping of input to output rows, unlike UDFs which are one-to-one or UDAFs which are many-to-one; they are used by specifying the UDTF in a SELECT clause or with a LATERAL VIEW join to join UDTF output rows back to input rows; at execution UDTFs use new operators like UDTFOperator and LateralViewJoinOperator while compilation involves detecting UDTFs and generating the correct operator DAG.
httplinux.die.netman3execfork() creates a new process by.docxadampcarr67227
http://linux.die.net/man/3/exec
fork() creates a new process by duplicating the calling process. The new process, referred to as the child, is an exact duplicate of the calling process, referred to as the parent#include <unistd.h>pid_t fork(void);
The exec() family of functions replaces the current process image with a new process image. The functions described in this manual page are front-ends for execve(2). (See the manual page for execve(2) for further details about the replacement of the current process image.)
The exec() family of functions include execl, execlp, execle, execv, execvp, and execvpe to execute a file.
The ANSI prototype for execl() is:
int execl(const char *path, const char *arg0,..., const char *argn, 0)
http://www.cems.uwe.ac.uk/~irjohnso/coursenotes/lrc/system/pc/pc4.htm #inciude <stdio.h> #inciude <unistd.h> main() { execl("/bin/ls", "ls", "-l", 0); printf("Can only get here on error\n"); }
The first parameter to execl() in this example is the full pathname to the ls command. This is the file whose contents will be run, provided the process has execute permission on the file. The rest of the execl() parameters provide the strings to which the argv array elements in the new program will point. In this example, it means that the ls program will see the string ls pointed to by its argv[0], and the string -l pointed to by itsargv[1]. In addition to making all these parameters available to the new program, the exec() calls also pass a value for the variable: extern char **environ;
This variable has the same format as the argv variable except that the items passed via environ are the values in the environment of the process (like any exported shell variables), rather than the command line parameters. In the case of execl(), the value of the environ variable in the new program will be a copy of the value of this variable in the calling process.
The execl() version of exec() is fine in the circumstances where you can ex-plicitly list all of the parameters, as in the previous example. Now suppose you want to write a program that doesn't just run ls, but will run any program you wish, and pass it any number of appropriate command line parameters. Obviously, execl() won't do the job.
The example program below, which implements this requirement, shows, however, that the system call execv() will perform as required: #inciude <stdio.h> main(int argc, char **argv) { if (argc==1) { printf("Usage: run <command> [<paraneters>]\n"); exit(1) } execv(argv[l], &argv[1)); printf("Sorry... couldn't run that!\n"); }
The prototype for execv() shows that it only takes two parameters, the first is the full pathname to the command to execute and the second is the argv value you want to pass into the new program. In the previous example this value was derived from the argv value passed into the run command, so that the run command can take the command line parameter values you pass it and just pass them on. int execl(.
The document provides an overview of the initialization phase of the Linux kernel. It discusses how the kernel enables paging to transition from physical to virtual memory addresses. It then describes the various initialization functions that are called by start_kernel to initialize kernel features and architecture-specific code. Some key initialization tasks discussed include creating an identity page table, clearing BSS, and reserving BIOS memory.
1 of 9 CSCE 3600 Systems Programming Major Assignm.docxShiraPrater50
1 of 9
CSCE 3600: Systems Programming
Major Assignment 2 – The Shell and System Calls
Due: 11:59 PM on Wednesday, November 6, 2019
COLLABORATION
You should complete this assignment as a group assignment with the other members of
your group as assigned on Canvas using our GitLab environment (i.e., the same group
you had for Major 1). If desired, you may submit only one program per group, but all
source code must be committed in GitLab. Also, make sure that you list the names of all
group members who participated in this assignment in order for each to get credit.
BACKGROUND
A shell provides a command-line interface for users. It interprets user commands and
executes them. Some shells provide simple scripting terms, such as if or while, and
allow users to make a program that facilitates their computing environment. Under the
hood, a shell is just another user program. The file /bin/bash is an executable file for
the bash shell. The only thing special about your login shell is that it is listed in your
login record so that /bin/login (i.e., the program that prompts you for your password)
knows what program to start when you log in. If you run "cat /etc/passwd", you will
see the login records of the machine.
PROGRAM DESCRIPTION
GROUP COLLABORATIVE PORTION
In this assignment, you will implement the shell “engine” as the “group” component,
where all members are responsible for the following functionality:
• A Command-Line Interpreter, or Shell
Your shell should read the line from standard input (i.e., interactive mode) or a
file (i.e., batch mode), parse the line with command and arguments, execute the
command with arguments, and then prompt for more input (i.e., the shell prompt)
when it has finished.
1. Interactive Mode
In interactive mode, you will display a prompt (any string of your choosing)
and the user of the shell will type in a command at the prompt.
2. Batch Mode
In batch mode, your shell is started by specifying a batch file on its command
line. The batch file contains the list of commands that should be executed. In
batch mode, you should not display a prompt, but you should echo each line
you read from the batch file back to the user before executing it.
You will need to use the fork() and exec() family of system calls. You may
2 of 9
not use the system() system call as it simply invokes the system’s /bin/bash
shell to do all of the work.
You may assume that arguments are separated by whitespace. You do not have
to deal with special characters such as ', ", \, etc. However, you will need to
handle the redirection operators (< and >) and the pipeline operator (|), which
will be specified in the “individual” portion of this assignment.
Each line (either in the batch file or typed at the prompt) may contain multiple
commands separate with the semicolon (;) character. Each command separated
by a ; should be run sequentially, but the shell should not print the next prompt ...
Shellcode is machine code that executes a shell when run. This document discusses shellcode, including:
- Shellcode injects machine code into a vulnerable application to spawn a shell.
- Three examples of shellcode are provided: an exit system call, displaying a message, and spawning a shell.
- Registers, assembly instructions, and system calls used in Linux are explained for creating shellcode.
हिंदी वर्णमाला पीपीटी, hindi alphabet PPT presentation, hindi varnamala PPT, Hindi Varnamala pdf, हिंदी स्वर, हिंदी व्यंजन, sikhiye hindi varnmala, dr. mulla adam ali, hindi language and literature, hindi alphabet with drawing, hindi alphabet pdf, hindi varnamala for childrens, hindi language, hindi varnamala practice for kids, https://www.drmullaadamali.com
This presentation includes basic of PCOS their pathology and treatment and also Ayurveda correlation of PCOS and Ayurvedic line of treatment mentioned in classics.
Macroeconomics- Movie Location
This will be used as part of your Personal Professional Portfolio once graded.
Objective:
Prepare a presentation or a paper using research, basic comparative analysis, data organization and application of economic information. You will make an informed assessment of an economic climate outside of the United States to accomplish an entertainment industry objective.
This presentation was provided by Steph Pollock of The American Psychological Association’s Journals Program, and Damita Snow, of The American Society of Civil Engineers (ASCE), for the initial session of NISO's 2024 Training Series "DEIA in the Scholarly Landscape." Session One: 'Setting Expectations: a DEIA Primer,' was held June 6, 2024.
Introduction to AI for Nonprofits with Tapp NetworkTechSoup
Dive into the world of AI! Experts Jon Hill and Tareq Monaur will guide you through AI's role in enhancing nonprofit websites and basic marketing strategies, making it easy to understand and apply.
Physiology and chemistry of skin and pigmentation, hairs, scalp, lips and nail, Cleansing cream, Lotions, Face powders, Face packs, Lipsticks, Bath products, soaps and baby product,
Preparation and standardization of the following : Tonic, Bleaches, Dentifrices and Mouth washes & Tooth Pastes, Cosmetics for Nails.
ISO/IEC 27001, ISO/IEC 42001, and GDPR: Best Practices for Implementation and...PECB
Denis is a dynamic and results-driven Chief Information Officer (CIO) with a distinguished career spanning information systems analysis and technical project management. With a proven track record of spearheading the design and delivery of cutting-edge Information Management solutions, he has consistently elevated business operations, streamlined reporting functions, and maximized process efficiency.
Certified as an ISO/IEC 27001: Information Security Management Systems (ISMS) Lead Implementer, Data Protection Officer, and Cyber Risks Analyst, Denis brings a heightened focus on data security, privacy, and cyber resilience to every endeavor.
His expertise extends across a diverse spectrum of reporting, database, and web development applications, underpinned by an exceptional grasp of data storage and virtualization technologies. His proficiency in application testing, database administration, and data cleansing ensures seamless execution of complex projects.
What sets Denis apart is his comprehensive understanding of Business and Systems Analysis technologies, honed through involvement in all phases of the Software Development Lifecycle (SDLC). From meticulous requirements gathering to precise analysis, innovative design, rigorous development, thorough testing, and successful implementation, he has consistently delivered exceptional results.
Throughout his career, he has taken on multifaceted roles, from leading technical project management teams to owning solutions that drive operational excellence. His conscientious and proactive approach is unwavering, whether he is working independently or collaboratively within a team. His ability to connect with colleagues on a personal level underscores his commitment to fostering a harmonious and productive workplace environment.
Date: May 29, 2024
Tags: Information Security, ISO/IEC 27001, ISO/IEC 42001, Artificial Intelligence, GDPR
-------------------------------------------------------------------------------
Find out more about ISO training and certification services
Training: ISO/IEC 27001 Information Security Management System - EN | PECB
ISO/IEC 42001 Artificial Intelligence Management System - EN | PECB
General Data Protection Regulation (GDPR) - Training Courses - EN | PECB
Webinars: https://pecb.com/webinars
Article: https://pecb.com/article
-------------------------------------------------------------------------------
For more information about PECB:
Website: https://pecb.com/
LinkedIn: https://www.linkedin.com/company/pecb/
Facebook: https://www.facebook.com/PECBInternational/
Slideshare: http://www.slideshare.net/PECBCERTIFICATION
This slide is special for master students (MIBS & MIFB) in UUM. Also useful for readers who are interested in the topic of contemporary Islamic banking.
Assessment and Planning in Educational technology.pptxKavitha Krishnan
In an education system, it is understood that assessment is only for the students, but on the other hand, the Assessment of teachers is also an important aspect of the education system that ensures teachers are providing high-quality instruction to students. The assessment process can be used to provide feedback and support for professional development, to inform decisions about teacher retention or promotion, or to evaluate teacher effectiveness for accountability purposes.
Executive Directors Chat Leveraging AI for Diversity, Equity, and InclusionTechSoup
Let’s explore the intersection of technology and equity in the final session of our DEI series. Discover how AI tools, like ChatGPT, can be used to support and enhance your nonprofit's DEI initiatives. Participants will gain insights into practical AI applications and get tips for leveraging technology to advance their DEI goals.
How to Manage Your Lost Opportunities in Odoo 17 CRMCeline George
Odoo 17 CRM allows us to track why we lose sales opportunities with "Lost Reasons." This helps analyze our sales process and identify areas for improvement. Here's how to configure lost reasons in Odoo 17 CRM
How to Manage Your Lost Opportunities in Odoo 17 CRM
Unix system calls
1. UNIX System Calls
UNIX System Calls
A system call is just what its name implies -- a request for the
operating system to do something on behalf of the user's program. The
system calls are functions used in the kernel itself. To the
programmer, the system call appears as a normal C function call.
However since a system call executes code in the kernel, there must be a
mechanism to change the mode of a process from user mode to kernel mode.
The C compiler uses a predefined library of functions (the C library)
that have the names of the system calls. The library functions
typically invoke an instruction that changes the process execution mode
to kernel mode and causes the kernel to start executing code for system
calls. The instruction that causes the mode change is often referred to
as an "operating system trap" which is a software generated interrupt.
The library routines execute in user mode, but the system call interface
is a special case of an interrupt handler. The library functions pass
the kernel a unique number per system call in a machine dependent way --
either as a parameter to the operating system trap, in a particular
register, or on the stack -- and the kernel thus determines the specific
system call the user is invoking. In handling the operating system
trap, the kernel looks up the system call number in a table to find the
address of the appropriate kernel routine that is the entry point for
the system call and to find the number of parameters the system call
expects. The kernel calculates the (user) address of the first
parameter to the system call by adding (or subtracting, depending on the
direction of stack growth) an offset to the user stack pointer,
corresponding to the number of the parameters to the system call.
Finally, it copies the user parameters to the "u area" and call the
appropriate system call routine. After executing the code for the
system call, the kernel determines whether there was an error. If so,
it adjusts register locations in the saved user register context,
typically setting the "carry" bit for the PS (processor status) register
and copying the error number into register 0 location. If there were no
errors in the execution of the system call, the kernel clears the
"carry" bit in the PS register and copies the appropriate return values
from the system call into the locations for registers 0 and 1 in the
saved user register context. When the kernel returns from the operating
system trap to user mode, it returns to the library instruction after
the trap instruction. The library interprets the return values from the
kernel and returns a value to the user program.
UNIX system calls are used to manage the file system, control processes,
and to provide interprocess communication. The UNIX system interface
consists of about 80 system calls (as UNIX evolves this number will
increase). The following table lists about 40 of the more important
system call:
-1-
2. GENERAL CLASS SPECIFIC CLASS SYSTEM CALL
---------------------------------------------------------------------
File Structure Creating a Channel creat()
Related Calls open()
close()
Input/Output read()
write()
Random Access lseek()
Channel Duplication dup()
Aliasing and Removing link()
Files unlink()
File Status stat()
fstat()
Access Control access()
chmod()
chown()
umask()
Device Control ioctl()
---------------------------------------------------------------------
Process Related Process Creation and exec()
Calls Termination fork()
wait()
exit()
Process Owner and Group getuid()
geteuid()
getgid()
getegid()
Process Identity getpid()
getppid()
Process Control signal()
kill()
alarm()
Change Working Directory chdir()
----------------------------------------------------------------------
Interprocess Pipelines pipe()
Communication Messages msgget()
msgsnd()
msgrcv()
msgctl()
Semaphores semget()
semop()
Shared Memory shmget()
shmat()
shmdt()
----------------------------------------------------------------------
[NOTE: The system call interface is that aspect of UNIX that has
changed the most since the inception of the UNIX system. Therefore,
when you write a software tool, you should protect that tool by putting
system calls in other subroutines within your program and then calling
only those subroutines. Should the next version of the UNIX system
change the syntax and semantics of the system calls you've used, you
need only change your interface routines.]
-2-
3. When a system call discovers and error, it returns -1 and stores the
reason the called failed in an external variable named "errno". The
"/usr/include/errno.h" file maps these error numbers to manifest
constants, and it these constants that you should use in your programs.
When a system call returns successfully, it returns something other than
-1, but it does not clear "errno". "errno" only has meaning directly
after a system call that returns an error.
When you use system calls in your programs, you should check the value
returned by those system calls. Furthermore, when a system call
discovers an error, you should use the "perror()" subroutine to print a
diagnostic message on the standard error file that describes why the
system call failed. The syntax for "perror()" is:
void perror(string)
char string;
"perror()" displays the argument string, a colon, and then the error
message, as directed by "errno", followed by a newline. The output of
"perror()" is displayed on "standard error". Typically, the argument
give to "perror()" is the name of the program that incurred the error,
argv[0]. However, when using subroutines and system calls on files, the
related file name might be passed to "perror()".
There are occasions where you the programmer might wish to maintain more
control over the printing of error messages than "perror()" provides --
such as with a formatted screen where the newline printed by "perror()"
would destroy the formatting. In this case, you can directly access the
same system external (global) variables that "perror()" uses. They are:
extern int errno;
extern char *sys_errlist[];
extern int sys_nerr;
"errno" has been described above. "sys_errlist" is an array (table) of
pointers to the error message strings. Each message string is null
terminated and does not contain a newline. "sys_nerr" is the number of
messages in the error message table and is the maximum value "errno" can
assume. "errno" is used as the index into the table of error messages.
Following are two sample programs that display all of the system error
messages on standard error.
-3-
4. /* errmsg1.c
print all system error messages using "perror()"
*/
#include <stdio.h>
int main()
{
int i;
extern int errno, sys_nerr;
for (i = 0; i < sys_nerr; ++i)
{
fprintf(stderr, "%3d",i);
errno = i;
perror(" ");
}
exit (0);
}
/* errmsg2.c
print all system error messages using the global error message table.
*/
#include <stdio.h>
int main()
{
int i;
extern int sys_nerr;
extern char *sys_errlist[];
fprintf(stderr,"Here are the current %d error messages:nn",sys_nerr);
for (i = 0; i < sys_nerr; ++i)
fprintf(stderr,"%3d: %sn", i, sys_errlist[i]);
}
-4-
5. Following are some examples in the use of the most often used system
calls.
File Structure Related System Calls
The file structure related system calls available in the UNIX system let
you create, open, and close files, read and write files, randomly access
files, alias and remove files, get information about files, check the
accessibility of files, change protections, owner, and group of files,
and control devices. These operations either use a character string
that defines the absolute or relative path name of a file, or a small
integer called a file descriptor that identifies the I/O channel. A
channel is a connection between a process and a file that appears to the
process as an unformatted stream of bytes. The kernel presents and
accepts data from the channel as a process reads and writes that
channel. To a process then, all input and output operations are
synchronous and unbuffered.
When doing I/O, a process specifies the file descriptor for an I/O
channel, a buffer to be filled or emptied, and the maximum size of data
to be transferred. An I/O channel may allow input, output, or both.
Furthermore, each channel has a read/write pointer. Each I/O operation
starts where the last operation finished and advances the pointer by the
number of bytes transferred. A process can access a channel's data
randomly by changing the read/write pointer.
All input and output operations start by opening a file using either the
"creat()" or "open()" system calls. These calls return a file
descriptor that identifies the I/O channel. Recall that file
descriptors 0, 1, and 2 refer to standard input, standard output, and
standard error files respectively, and that file descriptor 0 is a
channel to your terminal's keyboard and file descriptors 1 and 2 are
channels to your terminal's display screen.
creat()
The prototype for the creat() system call is:
int creat(file_name, mode)
char *file_name;
int mode;
where file_name is pointer to a null terminated character string that
names the file and mode defines the file's access permissions. The mode
is usually specified as an octal number such as 0666 that would mean
read/write permission for owner, group, and others or the mode may also
be entered using manifest constants defined in the
"/usr/include/sys/stat.h" file. If the file named by file_name does not
exist, the UNIX system creates it with the specified mode permissions.
However, if the file does exist, its contents are discarded and the mode
value is ignored. The permissions of the existing file are retained.
Following is an example of how to use creat():
-5-
6. /* creat.c */
#include <stdio.h>
#include <sys/types.h> /* defines types used by sys/stat.h */
#include <sys/stat.h> /* defines S_IREAD & S_IWRITE */
int main()
{
int fd;
fd = creat("datafile.dat", S_IREAD | S_IWRITE);
if (fd == -1)
printf("Error in opening datafile.datn");
else
{
printf("datafile.dat opened for read/write accessn");
printf("datafile.dat is currently emptyn");
}
close(fd);
exit (0);
}
The following is a sample of the manifest constants for the mode
argument as defined in /usr/include/sys/stat.h:
#define S_IRWXU 0000700 /* -rwx------ */
#define S_IREAD 0000400 /* read permission, owner */
#define S_IRUSR S_IREAD
#define S_IWRITE 0000200 /* write permission, owner */
#define S_IWUSR S_IWRITE
#define S_IEXEC 0000100 /* execute/search permission, owner */
#define S_IXUSR S_IEXEC
#define S_IRWXG 0000070 /* ----rwx--- */
#define S_IRGRP 0000040 /* read permission, group */
#define S_IWGRP 0000020 /* write " " */
#define S_IXGRP 0000010 /* execute/search " " */
#define S_IRWXO 0000007 /* -------rwx */
#define S_IROTH 0000004 /* read permission, other */
#define S_IWOTH 0000002 /* write " " */
#define S_IXOTH 0000001 /* execute/search " " */
Multiple mode values may be combined by or'ing (using the | operator)
the values together as demonstrated in the above sample program.
-6-
7. open()
Next is the open() system call. open() lets you open a file for
reading, writing, or reading and writing.
The prototype for the open() system call is:
#include <fcntl.h>
int open(file_name, option_flags [, mode])
char *file_name;
int option_flags, mode;
where file_name is a pointer to the character string that names the
file, option_flags represent the type of channel, and mode defines the
file's access permissions if the file is being created.
The allowable option_flags as defined in "/usr/include/fcntl.h" are:
#define O_RDONLY 0 /* Open the file for reading only */
#define O_WRONLY 1 /* Open the file for writing only */
#define O_RDWR 2 /* Open the file for both reading and writing*/
#define O_NDELAY 04 /* Non-blocking I/O */
#define O_APPEND 010 /* append (writes guaranteed at the end) */
#define O_CREAT 00400 /*open with file create (uses third open arg) */
#define O_TRUNC 01000 /* open with truncation */
#define O_EXCL 02000 /* exclusive open */
Multiple values are combined using the | operator (i.e. bitwise OR).
Note: some combinations are mutually exclusive such as: O_RDONLY |
O_WRONLY and will cause open() to fail. If the O_CREAT flag is used,
then a mode argument is required. The mode argument may be specified in
the same manner as in the creat() system call.
-7-
8. Following is an example of how to use open():
/* open.c */
#include <fcntl.h> /* defines options flags */
#include <sys/types.h> /* defines types used by sys/stat.h */
#include <sys/stat.h> /* defines S_IREAD & S_IWRITE */
static char message[] = "Hello, world";
int main()
{
int fd;
char buffer[80];
/* open datafile.dat for read/write access (O_RDWR)
create datafile.dat if it does not exist (O_CREAT)
return error if datafile already exists (O_EXCL)
permit read/write access to file (S_IWRITE | S_IREAD)
*/
fd = open("datafile.dat",O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
if (fd != -1)
{
printf("datafile.dat opened for read/write accessn");
write(fd, message, sizeof(message));
lseek(fd, 0L, 0); /* go back to the beginning of the file */
if (read(fd, buffer, sizeof(message)) == sizeof(message))
printf(""%s" was written to datafile.datn", buffer);
else
printf("*** error reading datafile.dat ***n");
close (fd);
}
else
printf("*** datafile.dat already exists ***n");
exit (0);
}
-8-
9. close()
To close a channel, use the close() system call. The prototype for the
close() system call is:
int close(file_descriptor)
int file_descriptor;
where file_descriptor identifies a currently open channel. close()
fails if file_descriptor does not identify a currently open channel.
read() write()
The read() system call does all input and the write() system call does
all output. When used together, they provide all the tools necessary to
do input and output sequentially. When used with the lseek() system
call, they provide all the tools necessary to do input and output
randomly.
Both read() and write() take three arguments. Their prototypes are:
int read(file_descriptor, buffer_pointer, transfer_size)
int file_descriptor;
char *buffer_pointer;
unsigned transfer_size;
int write(file_descriptor, buffer_pointer, transfer_size)
int file_descriptor;
char *buffer_pointer;
unsigned transfer_size;
where file_descriptor identifies the I/O channel, buffer_pointer points
to the area in memory where the data is stored for a read() or where
the data is taken for a write(), and transfer_size defines the maximum
number of characters transferred between the file and the buffer.
read() and write() return the number of bytes transferred.
There is no limit on transfer_size, but you must make sure it's safe to
copy transfer_size bytes to or from the memory pointed to by
buffer_pointer. A transfer_size of 1 is used to transfer a byte at a
time for so-called "unbuffered" input/output. The most efficient value
for transfer_size is the size of the largest physical record the I/O
channel is likely to have to handle. Therefore, 1K bytes -- the disk
block size -- is the most efficient general-purpose buffer size for a
standard file. However, if you are writing to a terminal, the transfer
is best handled in lines ending with a newline.
For an example using read() and write(), see the above example of
open().
-9-
10. lseek()
The UNIX system file system treats an ordinary file as a sequence of
bytes. No internal structure is imposed on a file by the operating
system. Generally, a file is read or written sequentially -- that is,
from beginning to the end of the file. Sometimes sequential reading and
writing is not appropriate. It may be inefficient, for instance, to
read an entire file just to move to the end of the file to add
characters. Fortunately, the UNIX system lets you read and write
anywhere in the file. Known as "random access", this capability is made
possible with the lseek() system call. During file I/O, the UNIX system
uses a long integer, also called a File Pointer, to keep track of the
next byte to read or write. This long integer represents the number of
bytes from the beginning of the file to that next character. Random
access I/O is achieved by changing the value of this file pointer using
the lseek() system call.
The prototype for lseek() is:
long lseek(file_descriptor, offset, whence)
int file_descriptor;
long offset;
int whence;
where file_descriptor identifies the I/O channel and offset and whence
work together to describe how to change the file pointer according to
the following table:
whence new position
------------------------------
0 offset bytes into the file
1 current position in the file plus offset
2 current end-of-file position plus offset
If successful, lseek() returns a long integer that defines the new file
pointer value measured in bytes from the beginning of the file. If
unsuccessful, the file position does not change.
Certain devices are incapable of seeking, namely terminals and the
character interface to a tape drive. lseek() does not change the file
pointer to these devices.
-10-
11. Following is an example using lseek():
/* lseek.c */
#include <stdio.h>
#include <fcntl.h>
int main()
{
int fd;
long position;
fd = open("datafile.dat", O_RDONLY);
if ( fd != -1)
{
position = lseek(fd, 0L, 2); /* seek 0 bytes from end-of-file */
if (position != -1)
printf("The length of datafile.dat is %ld bytes.n", position);
else
perror("lseek error");
}
else
printf("can't open datafile.datn");
close(fd);
}
-11-
12. Many UNIX systems have defined manifest constants for use as the
"whence" argument of lseek(). The definitions can be found in the
"file.h" and/or "unistd.h" include files. For example, the University
of Maryland's HP-9000 UNIX system has the following definitions:
from file.h we have:
#define L_SET 0 /* absolute offset */
#define L_INCR 1 /* relative to current offset */
#define L_XTND 2 /* relative to end of file */
and from unistd.h we have:
#define SEEK_SET 0 /* Set file pointer to "offset" */
#define SEEK_CUR 1 /* Set file pointer to current plus "offset" */
#define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
The definitions from unistd.h are the most "portable" across UNIX and
MS-DOS C compilers.
dup()
The dup() system call duplicates an open file descriptor and returns the
new file descriptor. The new file descriptor has the following
properties in common with the original file descriptor:
refers to the same open file or pipe.
has the same file pointer -- that is, both file descriptors share one
file pointer.
has the same access mode, whether read, write, or read and write.
The prototype for dup() is:
int dup(file_descriptor)
int file_descriptor;
where file_descriptor is the file descriptor describing the original I/O
channel returned by creat(), open(), pipe(), or dup() system calls.
dup() is guaranteed to return a file descriptor with the lowest integer
value available. It is because of this feature of returning the lowest
unused file descriptor available that processes accomplish I/O
redirection. The following example shows standard output redirected to
a file through the use of the dup() system call:
-12-
13. /* dup.c
demonstrate redirection of standard output to a file.
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int main()
{
int fd;
fd = open("foo.bar",O_WRONLY | O_CREAT, S_IREAD | S_IWRITE );
if (fd == -1)
{
perror("foo.bar");
exit (1);
}
close(1); /* close standard output */
dup(fd); /* fd will be duplicated into standard out's slot */
close(fd); /* close the extra slot */
printf("Hello, world!n"); /* should go to file foo.bar */
exit (0); /* exit() will close the files */
}
-13-
14. link()
The UNIX system file structure allows more than one named reference to a
given file, a feature called "aliasing". Making an alias to a file
means that the file has more than one name, but all names of the file
refer to the same data. Since all names refer to the same data,
changing the contents of one file changes the contents of all aliases to
that file. Aliasing a file in the UNIX system amounts to the system
creating a new directory entry that contains the alias file name and
then copying the i-number of a existing file to the i-number position of
this new directory entry. This action is accomplished by the link()
system call. The link() system call links an existing file to a new
file.
The prototype for link() is:
int link(original_name, alias_name)
char *original_name, *alias_name;
where both original_name and alias_name are character strings that name
the existing and new files respectively. link() will fail and no link
will be created if any of the following conditions holds:
a path name component is not a directory.
a path name component does not exist.
a path name component is off-limits.
original_name does not exist.
alias_name does exist.
original_name is a directory and you are not the superuser.
a link is attempted across file systems.
the destination directory for alias_name is not writable.
the destination directory is on a mounted read-only file system.
Following is a short example:
/* link.c
*/
#include <stdio.h>
int main()
{
if ((link("foo.old", "foo.new")) == -1)
{
perror(" ");
exit (1); /* return a non-zero exit code on error */
}
exit(0);
}
-14-
15. unlink()
The opposite of the link() system call is the unlink() system call.
unlink() removes a file by zeroing the i-number part of the file's
directory entry, reducing the link count field in the file's inode by 1,
and releasing the data blocks and the inode if the link count field
becomes zero. unlink() is the only system call for removing a file in
the UNIX system.
The prototype for unlink() is:
int unlink(file_name)
char *file_name;
where file_name names the file to be unlinked. unlink() fails if any of
the following conditions holds:
a path name component is not a directory.
a path name component does not exist.
a path name component is off-limits.
file_name does not exist.
file_name is a directory and you are not the superuser.
the directory for the file named by file_name is not writable.
the directory is contained in a file system mounted read-only.
It is important to understand that a file's contents and its inode are
not discarded until all processes close the unlinked file.
Following is a short example:
/* unlink.c
*/
#include <stdio.h>
int main()
{
if ((unlink("foo.bar")) == -1)
{
perror(" ");
exit (1); /* return a non-zero exit code on error */
}
exit (0);
}
-15-
16. Process Related System Calls
exec
The UNIX system provides several system calls to create and end program, to
send and receive software interrupts, to allocate memory, and to do other
useful jobs for a process. Four system calls are provided for creating a
process, ending a process, and waiting for a process to complete. These
system calls are fork(), the "exec" family, wait(), and exit().
The UNIX system calls that transform a executable binary file into a process
are the "exec" family of system calls. The prototypes for these calls are:
int execl(file_name, arg0 [, arg1, ..., argn], NULL)
char *file_name, *arg0, *arg1, ..., *argn;
int execv(file_name, argv)
char *file_name, *argv[];
int execle(file_name, arg0 [, arg1, ..., argn], NULL, envp)
char *file_name, *arg0, *arg1, ..., *argn, *envp[];
int execve(file_name, argv, envp)
char *file_name, *argv[], *envp[];
int execlp(file_name, arg0 [, arg1, ..., argn], NULL)
char *file_name, *arg0, *arg1, ..., *argn;
int execvp(file_name, argv)
char *file_name, *argv[];
where file_name names the executable binary file to be transformed into a
process, arg0 through argn and argv define the arguments to be passed to the
process, and envp defines the environment, also to be passed to the process.
By convention, arg0 and argv[0] name the last path name component of the
executable binary file named by file_name. For execl(), execv(), execle(),
and execve(), file_name must be the fully qualified path name of the
executable binary file. However for execlp() and execvp(), the PATH variable
is used to find the executable binary file. When the environment is not
explicitly given as an argument to an exec system call, the environment of
the current process is used. Furthermore, the last array element of both
argv and envp must be null to signify the end of the array.
Unlike the other system calls and subroutines, a successful exec system call
does not return. Instead, control is given to the executable binary file
named as the first argument. When that file is made into a process, that
process replaces the process that executed the exec system call -- a new
process is not created. If an exec call should fail, it will return a -1.
-16-
17. Letters added to the end of exec indicate the type of arguments:
l argn is specified as a list of arguments.
v argv is specified as a vector (array of character pointers).
e environment is specified as an array of character pointers.
p user's PATH is searched for command, and command can be a shell program
Following is a brief description of the six routines that make up the
collective family of exec routines:
execl Takes the path name of an executable program (binary file) as its
first argument. The rest of the arguments are a list of command
line arguments to the new program (argv[]). The list is
terminated with a null pointer:
execl("/bin/cat", "cat", "f1", "f2", (char *) 0);
execl("a.out", "a.out", (char *) 0);
Note that, by convention, the argument listed after the program
is the name of the command being executed (argv[0]).
execle Same as execl(), except that the end of the argument list is
followed by a pointer to a null-terminated list of character
pointers that is passed a the environment of the new program
(i.e., the place that getenv() searches for exported shell
variables):
static char *env[] = {
"TERM=vt100",
"PATH=/bin:/usr/bin",
(char *) 0 };
execle("/bin/cat", "cat", "f1", "f2", (char *) 0, env);
execv Takes the path name of an executable program (binary file) as it
first argument. The second argument is a pointer to a list of
character pointers (like argv[]) that is passed as command line
arguments to the new program:
static char *args[] = {
"cat",
"f1",
"f2",
(char *) 0 };
execv("/bin/cat", args);
-17-
18. execve Same as execv(), except that a third argument is given as a
pointer to a list of character pointers (like argv[]) that is
passed as the environment of the new program:
static char *env[] = {
"TERM=vt100",
"PATH=/bin:/usr/bin",
(char *) 0 };
static char *args[] = {
"cat",
"f1",
"f2",
(char *) 0 };
execve("/bin/cat", args, env);
execlp Same as execl(), except that the program name doesn't have to be
a full path name, and it can be a shell program instead of an
executable module:
execlp("ls", "ls", "-l", "/usr", (char *) 0);
execlp() searches the PATH environment variable to find the
specified program.
execvp Same as execv(), except that the program name doesn't have to be
a full path name, and it can be a shell program instead of an
executable module:
static char *args[] = {
"cat",
"f1",
"f2",
(char *) 0 };
execvp("cat", args);
When transforming an executable binary file into a process, the UNIX system
preserves some characteristics of the replaced process. Among the items
saved by the exec system call are:
The "nice" value for scheduling.
The process ID and the parent process ID.
The time left until an alarm clock signal.
The current working directory and the root directory.
The file creation mask as established with umask().
All open files.
The last of these is the most interesting because the shell uses this feature
to handle input/output redirection.
-18-
19. fork()
The exec family of system calls transforms an executable binary file into a
process that overlays the process that made the exec system call. The UNIX
system does not create a new process in response to an exec system call. To
create a new process, you must use the fork() system call. The prototype for
the fork() system call is:
int fork()
fork() causes the UNIX system to create a new process, called the "child
process", with a new process ID. The contents of the child process are
identical to the contents of the parent process.
The new process inherits several characteristics of the old process. Among
the characteristics inherited are:
The environment.
All signal settings.
The set user ID and set group ID status.
The time left until an alarm clock signal.
The current working directory and the root directory.
The file creation mask as established with umask().
The child process begins executing and the parent process continues executing
at the return from the fork() system call. This is difficult to understand
at first because you only call fork() once, yet it returns twice -- once per
process. To differentiate which process is which, fork() returns zero in the
child process and non-zero (the child's process ID) in the parent process.
exec routines are usually called after a call to fork(). This combination,
known as a fork/exec, allows a process to create a child to execute a
command, so that the parent doesn't destroy itself through an exec. Most
command interpreters (e.g. the shell) on UNIX use fork and exec.
wait()
You can control the execution of child processes by calling wait() in the
parent. wait() forces the parent to suspend execution until the child is
finished. wait() returns the process ID of a child process that finished.
If the child finishes before the parent gets around to calling wait(), then
when wait() is called by the parent, it will return immediately with the
child's process ID. (It is possible to have more that one child process by
simply calling fork() more than once.). The prototype for the wait() system
call is:
int wait(status)
int *status;
where status is a pointer to an integer where the UNIX system stores the
value returned by the child process. wait() returns the process ID of the
process that ended. wait() fails if any of the following conditions hold:
The process has no children to wait for.
status points to an invalid address.
-19-
20. The format of the information returned by wait() is as follows:
If the process ended by calling the exit() system call, the second lowest
byte of status is set to the argument given to exit() and the lowest byte
of status is set to zeroes.
If the process ended because of a signal, the second lowest byte of status
is set to zeroes and the lowest byte of status contains the signal number
that ended the process. If the seventh bit of the lowest byte of status
is set (i.e. status & 0200 == 0200) then the UNIX system produced a core
dump of the process.
exit()
The exit() system call ends a process and returns a value to it parent. The
prototype for the exit() system call is:
void exit(status)
int status;
where status is an integer between 0 and 255. This number is returned to the
parent via wait() as the exit status of the process. By convention, when a
process exits with a status of zero that means it didn't encounter any
problems; when a process exit with a non-zero status that means it did have
problems.
exit() is actually not a system routine; it is a library routine that call
the system routine _exit(). exit() cleans up the standard I/O streams before
calling _exit(), so any output that has been buffered but not yet actually
written out is flushed. Calling _exit() instead of exit() will bypass this
cleanup procedure. exit() does not return.
Following are some example programs that demonstrate the use of fork(),
exec(), wait(), and exit():
/* status.c
demonstrates exit() returning a status to wait().
*/
int main()
{
unsigned int status;
if ( fork () == 0 ) { /* == 0 means in child */
scanf ("%d", &status);
exit (status);
}
else { /* != 0 means in parent */
wait (&status);
printf("child exit status = %dn", status > 8);
}
}
Note: since wait() returns the exit status multiplied by 256 (contained in
the upper 8 bits), the status value is shifted right 8 bits (divided by 256)
to obtain the correct value.
-20-
21. /* myshell.c
This program is a simple command interpreter that uses execlp() to
execute commands typed in by the user.
*/
#include <stdio.h>
#define EVER ;;
int main()
{
int process;
char line[81];
for (EVER)
{
fprintf(stderr, "cmd: ");
if ( gets (line) == (char *) NULL) /* blank line input */
exit (0);
/* create a new process */
process = fork ();
if (process > 0) /* parent */
wait ((int *) 0); /* null pointer - return value not
saved */
else if (process == 0) /* child */
{ /* execute program */
execlp (line, line, (char *) NULL);
/* some problem if exec returns */
fprintf (stderr, "Can't execute %sn", line);
exit (1);
}
else if ( process == -1) /* can't create a new process */
{
fprintf (stderr, "Can't fork!n");
exit (2);
}
}
}
-21-
22. The following program demonstrates a practical use of fork() and exec() to
create a new directory. Only the superuser has the permission to use the
mknod() system call to create a new directory -- an ordinary user cannot use
mknod() to create a directory. So, we use fork/exec to call upon the UNIX
system's mkdir command that anyone can use to create a directory.
/* newdir.c
create a new directory, called newdir, using fork() and exec().
*/
#include <stdio.h>
int main()
{
int fd;
if ( fork() != 0)
wait ((int *) 0);
else
{
execl ("/bin/mkdir", "mkdir", "newdir", (char *) NULL);
fprintf (stderr, "exec failed!n");
exit (1);
}
/* now use newdir */
if ( (fd = open("newdir/foo.bar", O_RDWR | O_CREAT, 0644)) == -1)
{
fprintf (stderr, "open failed!n");
exit (2);
}
write (fd, "Hello, worldn", 14);
close (fd);
exit (0);
}
-22-
23. Software Interrupts
signal()
The UNIX system provides a facility for sending and receiving software
interrupts, also called SIGNALS. Signals are sent to a process when a
predefined condition happens. The number of signals available is system
dependent. For example, the University's HP-9000 has 31 signals defined.
The signal name is defined in /usr/include/sys/signal.h as a manifest
constant.
Programs can respond to signals three different ways. These are:
1. Ignore the signal. This means that the program will never be informed of
the signal no matter how many times it occurs. The only exception to this
is the SIGKILL signal which can neither be ignored nor caught.
2. A signal can be set to its default state, which means that the process
will be ended when it receives that signal. In addition, if the process
receives any of SIGQUIT, SIGILL, SIGIOT, SIGEMT, SIGFPE, SIGBUS, SIGSEGV, or
SIGSYS, the UNIX system will produce a core image (core dump), if possible,
in the directory where the process was executing when it received the
program-ending signal.
3. Catch the signal. When the signal occurs, the UNIX system will transfer
control to a previously defined subroutine where it can respond to the signal
as is appropriate for the program.
You define how you want to respond to a signal with the signal() system call.
The prototype is:
#include <sys/signal.h>
int (* signal ( signal_name, function ))
int signal_name;
int (* function)();
where signal_name is the name of the signal from signal.h and function is any
of SIG_IGN, meaning that you wish to ignore the signal when it occurs;
SIG_DFL, meaning that you wish the UNIX system to take the default action
when your program receives the signal; or a pointer to a function that
returns an integer. The function is given control when your program receives
the signal, and the signal number is passed as an argument. signal() returns
the previous value of function, and signal() fails if any of the following
conditions hold:
signal_name is an illegal name or SIGKILL.
function points to an invalid memory address.
-23-
24. Once a signal is caught, the UNIX system resets it to its initial state (the
default condition). In general, if you intend for your program to be able to
catch a signal repeatedly, you need to re-arm the signal handling mechanism.
You must do this as soon after receipt of the signal as possible, namely just
after entering the signal handling routine.
You should use signals in your programs to isolate critical sections from
interruption.
The state of all signals is preserved across a fork() system call, but all
caught signals are set to SIG_DFL across an exec system call.
kill()
The UNIX system sends a signal to a process when something happens, such as
typing the interrupt key on a terminal, or attempting to execute an illegal
instruction. Signals are also sent to a process with the kill() system call.
Its prototype is:
int kill (process_id, signal_name )
int process_it, signal_name;
where process_id is the ID of the process to be signaled and signal_name is
the signal to be sent to that process. If process_id has a positive value,
that value is assumed to be the process ID of the process to whom signal_name
signal is to be sent. If process_id has the value 0, then signal_name signal
is sent to all processes in the sending process' process group, that is all
processes that have been started from the same terminal. If process_id has
the value -1 and the process executing the kill() system call is the
superuser, then signal_name is sent to all processes excluding process 0 and
process 1 that have the same user ID as the process executing the kill().
kill() fails if any of the following conditions hold:
signal_name is not a valid signal.
there is not a process in the system with process ID process_id.
even though the process named by process_id is in the system, you cannot
send it a signal because your effective user ID does not match either the
real or effective user ID of process_id.
-24-
25. alarm()
Every process has an alarm clock stored in its system-data segment. When the
alarm goes off, signal SIGALRM is sent to the calling process. A child
inherits its parent's alarm clock value, but the actual clock isn't shared.
The alarm clock remains set across an exec.
The prototype for alarm() is:
unsigned int alarm(seconds)
unsigned int seconds;
where seconds defines the time after which the UNIX system sends the SIGALRM
signal to the calling process. Each successive call to alarm() nullifies the
previous call, and alarm() returns the number of seconds until that alarm
would have gone off. If seconds has the value 0, the alarm is canceled.
alarm() has no error conditions.
The following is an example program that demonstrates the use of the signal()
and alarm() system calls:
/* timesup.c */
#include <stdio.h>
#include <sys/signal.h>
#define EVER ;;
void main();
int times_up();
void main()
{
signal (SIGALRM, times_up); /* go to the times_up function */
/* when the alarm goes off. */
alarm (10); /* set the alarm for 10 seconds */
for (EVER) /* endless loop. */
; /* hope the alarm works. */
}
int times_up(sig)
int sig; /* value of signal */
{
printf("Caught signal #< %d >n", sig);
printf("Time's up! I'm outta here!!n");
exit(sig); /* return the signal number */
}
-25-
26. Interprocess Communication
UNIX System V allows processes to communicate with one another using pipes,
messages, semaphores, and shared memory. This sections describes how to
communicate using pipes.
One way to communicate between two processes is to create a pipeline with the
pipe() system call. pipe() builds the channel, but it is up to you to
connect the standard input of one process to the standard output of the other
process.
The prototype for pipe() is:
int pipe (file_descriptors)
int file_descriptors[2];
where file_descriptors[2] is an array that pipe() fills with a file
descriptor opened for reading, file_descriptor[0], and a file_descriptor
opened for writing, file_descriptor[1]. pipe() fails for the following
condition:
there are too many open I/O channels.
Some I/O system calls act differently on pipe file descriptors from the way
they do on ordinary files, and some do nothing at all. Following is a
summary of these actions:
write Data written to a pipe is sequenced in order of arrival.
Normally, is the pipe becomes full, write() will block until
enough old data is removed by read(). There are no partial
writes; the entire write() will be completed. The capacity of a
pipe varies with the UNIX implementation, but it is always at
least 4096 bytes (4K). If fcntl() is called to set the O_NDELAY
flag, write() will not block on a full pipe and will return a
count of 0. The only way to put an end-of-file on a pipe is to
close the writing file descriptor.
read Data is read from a pipe in order of arrival, just as it was
written. Once read, data can't be reread or put back. Normally,
if the pipe is empty, read will block until at least one byte of
data is available, unless the writing file descriptor is closed,
in which case the read will return a 0 count (the usual
end-of-file indication). But the byte count given as the third
argument to read will not necessarily be satisfied - only as many
bytes as are present at that instant will be read, and an
appropriate count will be returned. The byte count will never be
exceeded, of course; unread bytes will remain for the next
read(). If the O_NDELAY flag is set, a read() on an empty pipe
will return with a 0 count. This suffers from the same ambiguity
as reads on communication lines. A 0 count also means
end-of-file.
-26-
27. close Means more on a pipe than it does on a file. Not only does it
free up the file descriptor for reuse, but when the writing file
descriptor is closed it acts as an end-of-file for the reader.
If the read end file descriptor is closed, a write() on the other
file descriptor will cause and error. A fatal signal is also
normally generated (SIGPIPE - #13).
fcntl This system call sets or clears the O_NDELAY flag, whose effect
is described under write and read above.
fstat Not very useful on pipes. The size returned is the number of
bytes in the pipe, but this fact is seldom useful. A pipe may be
distinguished by a link count of 0, since a pipe is the only
source of a file descriptor associated with something not linked
into a directory. This distinction might be useful to I/O
routines that want to treat pipes specially.
open Not used with pipes.
creat Not used with pipes.
lseek Not used with pipes. This means that if a pipe contains a
sequence of messages, it isn't possible to look through them for
the message to read next. Like toothpaste in a tube, you have to
get it out to examine it, and then there is no way to put it
back.
Pipes use the buffer cache just as ordinary files do. Therefore, the
benefits of writing and reading pipes in units of a block (usually 512 or
1024 bytes) are just as great. A single write() execution is atomic, so if
512 bytes are written with a single system call, the corresponding read()
will return with 512 bytes (if it requests that many). It will not return
with less than the full block. However, if the writer is not writing
complete blocks, but the reader is trying to read complete blocks, the reader
may keep getting partial blocks anyway.
The following example program demonstrates how to set up a one-way pipe
between two related processes. Note that the processes MUST be related
(parent, child, grandchild, etc.) since the pipe mechanism is based on the
fact that file descriptors are inherited when a process is created. Error
checking in the following program has been minimized in order to keep the
code uncluttered and readable. In a "real" program more error checking on
the system calls should be done.
-27-
28. /* who_wc.c */
/* demonstrates a one-way pipe between two processes.
This program implements the equivalent of the shell command:
who | wc -l
which will count the number of users logged in.
*/
#include <stdio.h>
/* Define some manifest constants to make the code more understandable */
#define ERR (-1) /* indicates an error condition */
#define READ 0 /* read end of a pipe */
#define WRITE 1 /* write end of a pipe */
#define STDIN 0 /* file descriptor of standard in */
#define STDOUT 1 /* file descriptor of standard out */
int main()
{
int pid_1, /* will be process id of first child - who */
pid_2, /* will be process id of second child - wc */
pfd[2]; /* pipe file descriptor table. */
if ( pipe ( pfd ) == ERR ) /* create a pipe */
{ /* must do before a fork */
perror (" ");
exit (ERR);
}
if (( pid_1 = fork () ) == ERR) /* create 1st child */
{
perror (" ");
exit (ERR);
}
if ( pid_1 != 0 ) /* in parent */
{
if (( pid_2 = fork () ) == ERR) /* create 2nd child */
{
perror (" ");
exit (ERR);
}
if ( pid_2 != 0 ) /* still in parent */
{
close ( pfd [READ] ); /* close pipe in parent */
close ( pfd [WRITE] ); /* conserve file descriptors */
wait (( int * ) 0); /* wait for children to die */
wait (( int * ) 0);
}
-28-
29. else /* in 2nd child */
{
close (STDIN); /* close standard input */
dup ( pfd [READ] ); /* read end of pipe becomes stdin */
close ( pfd [READ] ); /* close unneeded I/O */
close ( pfd [WRITE] ); /* close unneeded I/O */
execl ("/bin/wc", "wc", "-l", (char *) NULL);
}
}
else /* in 1st child */
{
close (STDOUT); /* close standard out */
dup ( pfd [WRITE] ); /* write end of pipes becomes stdout */
close ( pfd [READ] ); /* close unneeded I/O */
close ( pfd [WRITE] ); /* close unneeded I/O */
execl ("/bin/who", "who", (char *) NULL);
}
exit (0);
}
The following is a diagram of the processes created by who_wc.
IMMMMMMMMMMMMMMMMMM;
: :
ZDDDDDDDDDDDDDDD: who_wc :DDDDDDDDDDDDD?
3 : : 3
3 HMMMMMMMMMMMMMMMMMM< 3
3 3
IMMMMMMMOMMMMMM; IMMMMMMOMMMMMMM;
: : : :
: who :DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD> wc -l :
: : pipe channel : :
HMMMMMMMMMMMMMM< HMMMMMMMQMMMMMM<
3
3
ZDDDDDDADDDDDD?
3 3
3 terminal 3
@DDDDDDDDDDDDDY
-29-
30. File Status
stat() - fstat()
The i-node data structure holds all the information about a file except the
file's name and its contents. Sometimes your programs need to use the
information in the i-node structure to do some job. You can access this
information with the stat() and fstat() system calls. stat() and fstat()
return the information in the i-node for the file named by a string and by a
file descriptor, respectively. The format for the i-node struct returned by
these system calls is defined in /usr/include/sys/stat.h. stat.h uses types
built with the C language typedef construct and defined in the file
/usr/include/sys/types.h, so it too must be included and must be included
before the inclusion of the stat.h file.
The prototypes for stat() and fstat() are:
#include <sys/types.h>
#include <sys/stat.h>
int stat(file_name, stat_buf)
char *file_name;
struct stat *stat_buf;
int fstat(file_descriptor, stat_buf)
int file_descriptor;
struct stat *stat_buf;
where file_name names the file as an ASCII string and file_descriptor names
the I/O channel and therefore the file. Both calls returns the file's
specifics in stat_buf. stat() and fstat() fail if any of the following
conditions hold:
a path name component is not a directory (stat() only).
file_name does not exit (stat() only).
a path name component is off-limits (stat() only).
file_descriptor does not identify an open I/O channel (fstat() only).
stat_buf points to an invalid address.
Following is an extract of the stat.h file from the University's HP-9000. It
shows the definition of the stat structure and some manifest constants used
to access the st_mode field of the structure.
-30-
31. /* stat.h */
struct stat
{
dev_t st_dev; /* The device number containing the i-node */
ino_t st_ino; /* The i-number */
unsigned short st_mode; /* The 16 bit mode */
short st_nlink; /* The link count; 0 for pipes */
ushort st_uid; /* The owner user-ID */
ushort st_gid; /* The group-ID */
dev_t st_rdev; /* For a special file, the device number */
off_t st_size; /* The size of the file; 0 for special files */
time_t st_atime; /* The access time. */
int st_spare1;
time_t st_mtime; /* The modification time. */
int st_spare2;
time_t st_ctime; /* The status-change time. */
int st_spare3;
long st_blksize;
long st_blocks;
uint st_remote:1; /* Set if file is remote */
dev_t st_netdev; /* ID of device containing */
/* network special file */
ino_t st_netino; /* Inode number of network special file */
long st_spare4[9];
};
#define S_IFMT 0170000 /* type of file */
#define S_IFDIR 0040000 /* directory */
#define S_IFCHR 0020000 /* character special */
#define S_IFBLK 0060000 /* block special */
#define S_IFREG 0100000 /* regular (ordinary) */
#define S_IFIFO 0010000 /* fifo */
#define S_IFNWK 0110000 /* network special */
#define S_IFLNK 0120000 /* symbolic link */
#define S_IFSOCK 0140000 /* socket */
#define S_ISUID 0004000 /* set user id on execution */
#define S_ISGID 0002000 /* set group id on execution */
#define S_ENFMT 0002000 /* enforced file locking (shared with S_ISGID)*/
#define S_ISVTX 0001000 /* save swapped text even after use */
Following is an example program demonstrating the use of the stat() system
call to determine the status of a file:
-31-
32. /* status.c */
/* demonstrates the use of the stat() system call to determine the
status of a file.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#define ERR (-1)
#define TRUE 1
#define FALSE 0
int main();
int main(argc, argv)
int argc;
char *argv[];
{
int isdevice = FALSE;
struct stat stat_buf;
if (argc != 2)
{
printf("Usage: %s filenamen", argv[0]);
exit (1);
}
if ( stat( argv[1], &stat_buf) == ERR)
{
perror("stat");
exit (1);
}
printf("nFile: %s status:nn",argv[1]);
if ((stat_buf.st_mode & S_IFMT) == S_IFDIR)
printf("Directoryn");
else if ((stat_buf.st_mode & S_IFMT) == S_IFBLK)
{
printf("Block special filen");
isdevice = TRUE;
}
else if ((stat_buf.st_mode & S_IFMT) == S_IFCHR)
{
printf("Character special filen");
isdevice = TRUE;
}
else if ((stat_buf.st_mode & S_IFMT) == S_IFREG)
printf("Ordinary filen");
else if ((stat_buf.st_mode & S_IFMT) == S_IFIFO)
printf("FIFOn");
-32-
33. if (isdevice)
printf("Device number:%d, %dn", (stat_buf.st_rdev > 8) & 0377,
stat_buf.st_rdev & 0377);
printf("Resides on device:%d, %dn", (stat_buf.st_dev > 8) & 0377,
stat_buf.st_dev & 0377);
printf("I-node: %d; Links: %d; Size: %ldn", stat_buf.st_ino,
stat_buf.st_nlink, stat_buf.st_size);
if ((stat_buf.st_mode & S_ISUID) == S_ISUID)
printf("Set-user-IDn");
if ((stat_buf.st_mode & S_ISGID) == S_ISGID)
printf("Set-group-IDn");
if ((stat_buf.st_mode & S_ISVTX) == S_ISVTX)
printf("Sticky-bit set -- save swapped text after usen");
printf("Permissions: %on", stat_buf.st_mode & 0777);
exit (0);
}
access()
To determine if a file is accessible to a program, the access() system call
may be used. Unlike any other system call that deals with permissions,
access() checks the real user-ID or group-ID, not the effective ones.
The prototype for the access() system call is:
int access(file_name, access_mode)
char *file_name;
int access_mode;
where file_name is the name of the file to which access permissions given in
access_mode are to be applied. Access modes are often defined as manifest
constants in /usr/include/sys/file.h. The available modes are:
Value Meaning file.h constant
----- ------ ------
00 existence F_OK
01 execute X_OK
02 write W_OK
04 read R_OK
These values may be ORed together to check for mone than one access
permission. The call to access() returns 0 if the program has the given
access permissions, otherwise -1 is returned and errno is set to the reason
for failure. This call is somewhat useful in that it makes checking for a
specific permission easy. However, it only answers the question "do I have
this permission?" It cannot answer the question "what permissions do I
have?"
-33-
34. The following example program demonstrates the use of the access() system
call to remove a file. Before removing the file, a check is made to make
sure that the file exits and that it is writable (it will not remove a
read-only file).
/* remove.c */
#include <stdio.h>
#include <sys/file.h>
#define ERR (-1)
int main();
int main(argc, argv)
int argc;
char *argv[];
{
if (argc != 2)
{
printf("Usage: %s filenamen", argv[0]);
exit (1);
}
if (access (argv[1], F_OK) == ERR) /* check that file exists */
{
perror(argv[1]);
exit (1);
}
if (access (argv[1], W_OK) == ERR) /* check for write permission */
{
fprintf(stderr,"File: %s is write protected!n", argv[1]);
exit (1);
}
if (unlink (argv[1]) == ERR)
{
perror(argv[1]);
exit (1);
}
exit (0);
}
-34-
35. Miscellaneous System Calls / Examples
Directories
A directory is simply a special file that contains (among other information)
i-number/filename pairs. With the exception of 4.2 and 4.3 BSD, all versions
of the UNIX system limit filenames to 14 characters. These short filenames
make for a simple fixed size directory format on System V.
System V Directories
A directory contains structures of type direct, defined in the include file
/usr/include/sys/dir.h. The include file /usr/include/sys/types.h must also
be included to define the types used by the structure. The directory
structure is:
#define DIRSIZ 14
struct direct {
ino_t d_ino;
char d_name[DIRSIZ];
};
It should be noted that the name of the file, d_name is NOT guaranteed to be
null-terminated; programs should always be careful of this. Files which have
been deleted will have i-numbers (d_ino) equal to zero; these should in
general be skipped over when reading the directory. A directory is read
simply by opening it (in read-only mode) and reading structures either one at
a time or all at once. The following example program simply opens the
current directory and prints the names of all the files it contains. The
program simulates the ls -a command. Note that the file names are not sorted
like the real ls command would do.
/* my_ls.c
This program simulates the System V style ls -a command. Filenames
are printed as they occur in the directory -- no sorting is done.
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/dir.h>
#define ERR (-1)
int main()
{
int fd;
struct direct dir;
if (( fd = open (".", O_RDONLY)) == ERR) /* open current directory */
{
perror("open");
exit (1);
}
-35-
36. while (( read (fd, &dir, sizeof (struct direct)) > 0 )
{
if ( dir.d_ino == 0 ) /* is it a deleted file? */
continue; /* yes, so go read another */
/* make sure we print no more than DIRSIZ characters */
printf ("%.*sn", DIRSIZ, dir.d_name);
}
close (fd);
exit (0);
}
If you need more information about the file such as size or permissions, you
would use the stat() system call to obtain it.
Berkeley Style Directories
A directory contains structures of type direct, defined in the include file
/usr/include/sys/ndir.h. The include file /usr/include/sys/types.h must also
be included to define the types used by the structure. The directory
structure is:
#define MAXNAMLEN 255
#define DIRSIZ_CONSTANT 14 /* equivalent to DIRSIZ */
struct direct {
long d_fileno; /* file number of entry */
short d_reclen; /* length of this record */
short d_namlen; /* length of string in d_name */
char d_name[MAXNAMLEN + 1]; /* name (up to MAXNAMLEN + 1) */
};
#if !(defined KERNEL) && !(defined ATT3B2)
#define d_ino d_fileno /* compatibility */
Unlike on System V, filenames can be longer than 14 characters and the size
of a directory structure can be variable. Therefore, the read() call can not
be used to read the directory. Instead, Berkely style systems provide a set
of library functions to read directories. These functions are also declared
in the ndir.h include file. They are:
extern DIR *opendir();
extern struct direct *readdir();
extern long telldir();
extern void seekdir();
#define rewinddir(dirp) seekdir((dirp), (long)0)
extern void closedir();
-36-
37. The following example shows how to perform a Berkeley (or HP) style ls -a
read of a directory. One important note: filenames in the directory
structure are null-terminated in Berkeley style systems -- on System V they
are not.
#include <stdio.h>
#include <sys/types.h>
#include <ndir.h>
main()
{
DIR *dirp;
struct direct *dp;
dirp = opendir("."); /* open the current directory */
while ((dp = readdir(dirp)) != NULL)
{
if (dp->d_ino == 0) /* ignore deleted files */
continue;
else
printf("%sn",dp->d_name); /* the name is null-terminated */
}
}
For more information, type: man directory while logged onto the
University's HP system.
-37-
38. Time
The UNIX operating system keeps track of the current date and time by storing
the number of seconds that have elasped since midnight January 1, 1970 UTC
(Coordinated Universal Time, also known as Greenwich Mean Time (GMT)). This
date is considered the informal "birthday" of the UNIX operating system. The
time is stored in a signed long integer. (For the curious, assuming a 32 bit
signed long integer, UNIX time will break at 03:14:08 January 19, 2038 UTC.)
In all versions of UNIX, the time() system call may be used to obtain the
time of day. This call is peculiar in that if given the address of a long
integer as an argument, it places the time in that integer and returns it.
If, however, a null pointer is passed, the time of day is just returned.
Several routines are available to convert the long integer returned by time()
into an ASCII date string. With the UNIX operating system, an ASCII date
string is a string as shown below:
Day Mon dd hh:mm:ss yyyy
For example: Sat Mar 24 11:03:36 1990
The ctime() library function can be used to do the above conversion. An
example is:
/* my_date.c
print the current date and time in a format similar to the output
of the date command.
*/
#include <stdio.h>
#include <time.h> /* may need to be #include <sys/time.h> instead */
int main()
{
long now, time();
char *ctime();
time (&now);
printf("It is now %sn", ctime (&now));
exit (0);
}
-38-
39. Often you need access to specific information about the current date and
time. The localtime() and gmtime() functions will provide it. They do this
by converting the long integer returned by time() into a data structure
called tm, which is defined in the time.h header file. In fact, this is what
the header file looks like:
struct tm {
int tm_sec; /* seconds after the minute - [0,59] */
int tm_min; /* minutes after the hour - [0,59] */
int tm_hour; /* hours since midnight - [0,23] */
int tm_mday; /* day of the month - [1,31] */
int tm_mon; /* months since January - [0,11] */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday - [0,6] */
int tm_yday; /* days since January 1 - [0,365] */
int tm_isdst; /* daylight savings time flag */
};
As you can see, there is quite a bit of information you can access. The
tm_isdst member is non-zero if Daylight Savings Time is in effect. The
localtime() function returns the time in the local time zone, whereas the
gmtime() function returns the time in the UTC (or GMT) time zone. Both
localtime() and gmtime() take as their argument a pointer to a long integer
that represents the date and time as the number of seconds since January 1,
1970 (such a returned by time() ). The return pointers to a tm structure,
where the converted data is placed. The following example prints the local
date in the familiar mm/dd/yy format:
/* day.c
print date in mm/dd/yy format
*/
#include <stdio.h>
#include <time.h> /* may need to be #include <sys/time.h> instead */
int main()
{
long now, time();
struct tm *today, *localtime();
time (&now);
today = localtime (&now);
printf("Today is: %d/%d/%dn", today->tm_mon + 1, today->tm_mday,
today->tm_year);
exit (0);
}
-39-
40. Parsing Input
When dealing with input from a command line, the first step is to parse
(break up) the input line into tokens, which are groups of characters that
form syntactic units; examples are words, strings, and special symbols.
Following are some sample programs and functions that demonstrate various
ways to parse an input line:
/* parse.c
Split the input buffer into individual tokens. Tokens are
assumed to be separated by space or tab characters.
A pointer to each token is stored in an array of pointers.
This method is very similar to the argv argument to main().
*/
#include <stdio.h>
#define EVER ;;
#define MAXARG 64
int main()
{
char buf[256];
char *args[MAXARG]; /* accept MAXARG number of tokens */
int num_arg,
lcv;
for (EVER)
{
printf("Enter line: ");
if ((gets(buf)) == (char *) NULL)
{
putchar('n');
exit(0);
}
num_arg = parse_cmd(buf, args);
printf("Number of tokens = %dn",num_arg);
for (lcv = 0; lcv < num_arg; lcv++)
puts(args[lcv]);
}
}
-40-
41. int parse_cmd(buf, args)
char *buf;
char **args;
{
int count = 0;
while (*buf != '0' && count < MAXARG)
{
while ((*buf == ' ') || (*buf == 't'))
*buf++ = '0';
*args++ = buf;
++count;
while ((*buf != '0') && (*buf != ' ') && (*buf != 't'))
buf++;
}
*args = (char *) NULL; /* make the last element of the array null */
return(count); /* return the number of tokens parsed */
}
There is a C library function available that makes parsing a string into
tokens very easy; it is strtok(). Following is the above function (parse_cmd
() ) as implemented using strtok():
int parse_cmd(line, args)
char *line;
char *args[];
{
int count = 0;
char *str, *strtok();
static char delimiters[] = " tn";
while (( str = strtok(line, delimiters)) != (char *) NULL)
{
line = (char *) NULL;
args[count++] = str;
}
args[count] = (char *) NULL;
return(count);
}
strtok() takes as arguments a pointer to the input string and a pointer to a
string containing the character or characters that delimit the token. In the
above example, the delimiters were defined to be a space, tab, or newline.
You are free to change the delimiter at any time. If you wish strtok() to
parse the complete line, you must pass a null-pointer on the second and
subsequent calls to strtok() (note that "line" was set to null inside the
body of the while loop). strtok() returns a null-pointer when the end of the
input string is reached.
strtok() is very useful in parsing the individual path elements as defined in
the PATH environment variable (set the delimiter to ":" ).
-41-
42. CURSES
What is curses? curses is a terminal-independent library of C routines and
macros that you use to write "window-based" screen management programs on the
UNIX system. curses is designed to let programmers control terminal I/O in
an easy fashion. Providing an easy-to-use "human interface" for users is an
increasingly important requirement for operating systems. Such a connection
between the machine and the humans that use it plays an important role in the
overall productivity of the system. curses gets its name from what it does:
cursor manipulation.
What can curses do? Among the functions to be found in curses are those
that:
- Move the cursor to any point on the screen
- Insert text anywhere on the screen, doing it even in highlight mode
- Divide the screen into rectangular areas called windows
- Manage each window independently, so you can be scrolling one window
while erasing a line in another
- Draw a box around a window using a character of your choice
- Write output to and read input from a terminal screen
- Control the data output and input -- for example, to print output in
bold type or prevent it from echoing (printing back on a screen)
- Draw simple graphics
If these features leave you unimpressed, remember that they are only tools.
When you use these tools in your programs, the results can be spectacular.
The point is -- curses is easy to use and ready to go -- so that you can
concentrate on what you want your program to do. curses will make you
program look sharp.
Where did curses come from? The author of curses in Ken Arnold who wrote the
package while a student at the University of California, Berkeley. At the
same time, Bill Joy was writing his editor program, vi. Ken Arnold credits
Bill Joy with providing the ideas (as well as code) for creating the
capability to generally describe terminals, writing routines to read the
terminal database, and implementing routines for optimal cursor movement.
The original source of information about curses is Ken Arnold's paper
entitled "Screen Updating and Cursor Movement Optimization: A Library
Package".
What makes curses tick? The original version of curses developed by Ken
Arnold incorporated a database known as termcap, or the terminal capabilities
database. In System V Release 2, the termcap database was replaced by the
terminfo data base, and curses was rewritten to incorporate it. Both of
these versions of curses can be used with more than one hundred terminals.
The information in the termcap or terminfo database is used by the curses
routines to determine what sequence of special characters must be sent to a
particular terminal to cause it to clear the screen, move the cursor up one
line, delete a line, etc. It is these databases that make curses truly
terminal independent, since any terminal not already in the database can be
added by a system administrator, and since the structure of both databases
allows users to add their own local additions or modifications for a
particular terminal.
-42-
43. How to use curses -- the basics: There are a couple of things you have to
know before you can start using the curses library. First, when you compile
a C program that call curses routines, you must specify to the cc command
that the curses library is to be linked in with the program. This is done
with the -lcurses option, which must be specified after all the C program
files. The following is an example cc command line for use on systems that
support the terminfo database:
cc myprog.c -lcurses
Next is an example cc command line for use on systems that support the
termcap database:
cc myprog.c -lcurses -ltermlib
Second, all program files that reference curses routines must include the
header file <curses.h><curses.h> will include the header <stdio.h> so it
is not necessary for your program to include it. It won't hurt anything if
you do -- it just slows down the compilation. Lastly, before you run a
program that uses curses, you must inform curses what type of terminal you
have. You do this by setting the shell variable TERM to the type of terminal
you are using (e.g. a DEC VT100) and exporting the TERM variable into the
environment. This is done in the following manner:
$ TERM=vt100
$ export TERM
This action is usually done for you by your .profile when you log it.
The <curses.h> header file contains declarations for variables, constants,
data structures and macros. Among the variables are two integer variables
that prove to be very useful: LINES and COLS. LINES is automatically set to
the number of lines on your terminal; COLS is set to the number of columns.
Many of the curses routines address the terminal's screen, in that they move
the cursor to a specific place, or address. This address is specified as a
particular row and column (specified as arguments to the routine), where the
address of the upper left-hand corner is row LINES-1 and column COLS-1
(LINES-1, COLS-1). Following is a layout of the terminal screen:
IMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM;
:(0,0) (0, COLS-1):
: :
: :
R : :
O : :
W : . :
: (row,col) :
: :
: :
: :
:(LINES-1,0) (LINES-1, COLS-1):
HMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM<
COLUMN
-43-
44. All programs using the curses library must have the following basic
structure:
#include <curses.h>
main()
{
initscr();
/* main program */
endwin();
}
The initscr() function must be called before any other curses routines. Its
function is to determine the terminal type from the TERM environment variable
and to initialize certain data structures and variables (e.g. LINES and
COLS). The endwin() function should be called prior to program exit to
restore the terminal's original state. Some curses routines change the
terminal's characteristics (e.g. go into raw mode and turn off echoing) and
must be undone before the program exits; otherwise the terminal is left in an
odd state and the user may not know how to change it back. Here is how to
fix the terminal if a curses program leaves it in a "funny" state:
on System III and System V UNIX systems (including XENIX) type:
stty sane ctrl-j
note that you must type a control-j and not the return key, since most likely
NEWLINE mapping will be off and the RETURN key will not work.
on Berkeley UNIX systems type:
stty -raw -cbreak -nl echo ek ctrl-j
Windows and screens: Conceptually, a window is an independent rectangular
area of characters displayed on the screen. Physically, a window is a
WINDOW, that is, a C data structure that holds all the information about a
window.
The Standard Screen - stdscr: The traditional definition of the "standard
screen" is a window or a set of windows that fills the entire screen of a
video display terminal. The structure that describes stdscr is a WINDOW, or
more precisely, a pointer to a WINDOW. A WINDOW is a character array that
maintains an image of the terminal screen, known as the screen image. The
screen image array in stdscr is automatically made the length and width of
the terminal screen. Thus, there is one character in that array for every
place on the screen.
-44-
45. The Current Screen - curscr: curses does not know directly what the terminal
is displaying; it would be even slower to have to query the terminal to find
out what character is being displayed at each location. Instead, curses
keeps and image of what it thinks the screen looks like in a window called
curscr. curscr, like stdscr, is created automatically when you initialize
curses with initscr(). curscr is a WINDOW, and has a screen image the size
of the physical screen. When refresh() is called, it writes the characters
that it is sending to the terminal into their corresponding location in the
screen image of curscr. curscr contains the image of the screen as curses
thinks it was made to look by the last refresh(). refresh() uses the screen
image in curscr to minimize its work. When it goes to refresh a window, it
compares the contents of that window to curscr. refresh() assumes that the
physical screen looks like curscr so it does not output characters that are
the same in curscr and the window that is being refreshed. In this way,
refresh() minimizes the number of characters that it sends to the screen and
save a great deal of time.
The following are a few of the more commonly used curses routines. The list
is not comprehensive:
Terminal Modes: the terminal modes for I/O are usually set after the call to
initscr(). None of the mode setting routines accept parameters.
echo() / noecho() These functions allow programmers to turn on or
off the terminal driver's echoing to the terminal.
The default state is echo on. The function
noecho() disables the automatic echoing.
nl() / nonl() These functions allow programmers to enable or
disable carriage return/newline mappings. When
enabled, carriage return is mapped on input to
newline and newline is mapped on output to
newline/carriage return. The default state is
mapping enabled., and nonl() is used to turn this
mapping off. It is interesting to note that while
mapping is disabled, cursor movement is optimized.
cbreak() / nocbreak() Canonical processing (line at a time character
processing) is disabled within the terminal driver
when calling cbreak(), allowing a break for each
character. Interrupt and flow control keys are
unaffected. The default state is nocbreak, which
enables canonical processing.
raw() / noraw() These functions are similar to the cbreak() /
nocbreak() functions, except that interrupt and
flow control key are also disabled or enabled.
savetty() / resetty() The current state of the terminal can be saved
into a buffer reserved by curses when calling
savetty() function. The last save state can be
restored via the resetty() function.
gettmode() This function is used to establish the current tty
mode while in curses. It reads the baud rate of
the terminal, turns off the mapping of carriage
returns to line feeds on output, and the expansion
of tabs into spaces by the system.
-45-
46. I/O Function:
addch() This function adds a character to a window at the current
cursor position.
#include <curses.h>
main()
{
initscr();
addch('e');
refresh();
endwin();
}
mvaddch() This function moves a character into a window at the
position specified by the x and y coordinates.
#include <curses.h>
main()
{
int x,y;
x = 3; y = 10;
initscr();
mvaddch(x, y, 'e');
refresh();
endwin();
}
addstr() This function adds the specified string to a window at the
current cursor position.
#include <curses.h>
main()
{
initscr();
addstr("This is a string example.");
refresh();
endwin();
}
mvaddstr() This function moves the specified string into a window
located at the position specified by the x and y
coordinates.
#include <curses.h>
main()
{
int x,y;
x = 3; y = 10;
initscr();
mvaddstr(x, y, "This is the string example.");
refresh();
endwin();
}
-46-
47. printw() This function outputs formatted strings at the current
cursor position and is similar to the printf() function of
C, in that multiple arguments may be specified.
#include <curses.h>
main()
{
static char *word = "example";
int number = 1;
initscr();
printw("this is just %d %s of a formatted string!n",number,word);
refresh();
endwin();
}
mvprintw() This function outputs formatted strings at the line
specified in y and the column specifed in x. Multiple
arguments may be given.
#include <curses.h>
main()
{
static char *word = "example";
int number = 1;
int x = 3, y = 10;
initscr();
mvprintw(x ,y, "this is just %d %s of a formatted string!n",
number,word);
refresh();
endwin();
}
move() This function moves the cursor to the line/column
coordinates given.
#include <curses.h>
main()
{
int line = 3, column = 10;
initscr();
move(line, column);
refresh();
endwin();
}
getyx() This function is used to determine and return the current
line/column location of the cursor.
#include <curses.h>
main()
{
WINDOW *win;
int y, x;
initscr();
win = newwin(10,5,12,39);
getyx(win, y, x)
refresh();
endwin();
}
-47-
48. getch() This function is used to read a single character from the
keyboard, and returns an integer value. It is similar to
the the C standard I/O function getc();
#include <curses.h>
main()
{
int in_char;
initscr();
in_char = getch();
refresh();
endwin();
}
inch() This function returns the character from under the current
cursor position of the terminals screen, in an integer.
#include <curses.h>
main()
{
int in_char;
initscr();
in_char = inch();
refresh();
endwin();
}
mvinch() This function is used to get the character under the cursor
location specified as x and y coordinates. The value
returned is an integer.
#include <curses.h>
main()
{
int in_char;
initscr();
in_char = mvinch(3, 10);
refresh();
endwin();
}
clear() This function completely clear the terminal screen by
writing blank spaces to all physical screen locations via
calls to erase() and clearok(), and is completed by the
next call to refresh().
#include <curses.h>
main()
{
initscr();
clear()
refresh();
endwin();
}
-48-
49. erase() This function is used to insert blank spaces in the
physical screen and, like clear(), erases all data on the
terminal screen, but does not require a call to refresh().
#include <curses.h>
main()
{
initscr();
erase()
endwin();
}
clrtobot() This function is used to clear the physical screen from the
current cursor position to the bottom of the screen,
filling it with blank spaces.
#include <curses.h>
main()
{
initscr();
clrtobot();
refresh();
endwin();
}
clrtoeol() This function is used to clear the physical screen from the
current cursor position to the end of the physical screen
line by filling it with blank spaces.
#include <curses.h>
main()
{
initscr();
clrtoeol();
refresh();
endwin();
}
delch() This function deletes the character under the current
cursor position, moving all characters on that line
(located to the right of the deleted character) one
position to the left, and fills the last character position
(on that line) with a blank space. The current cursor
position remains unchanged.
#include <curses.h>
main()
{
initscr();
delch();
refresh();
endwin();
}
-49-
50. mvdelch() This function deletes the character under the cursor
position at the line/column specified in y/x. In all other
respects, it works the same as the delch() function,
#include <curses.h>
main()
{
initscr();
mvdelch(3, 10);
refresh();
endwin();
}
insch() This function is used to insert the character named in 'c'
to be inserted at the current cursor position, causing all
characters to the right of the cursor (on that line, only)
to shift one space to the right, losing the last character
of that line. The cursor is moved one position to the
right of the inserted character.
#include <curses.h>
main()
{
initscr();
insch('c');
refresh();
endwin();
}
mvinsch() This function inserts the character named in 'c' to the
line/column position named in y/x, and otherwise works
identically to the insch() function.
#include <curses.h>
main()
{
initscr();
mvinsch(3, 10, 'c');
refresh();
endwin();
}
deleteln() This function allows the deletion of the current cursor
line, moving all lines located below up one line and
filling the last line with blank spaces. The cursor
position remains unchanged.
#include <curses.h>
main()
{
initscr();
deleteln();
refresh();
endwin();
}
-50-
51. insertln() This function inserts a blank filled line at the current
cursor line, moving all lines located below down one line.
The bottom line is lost, and the current cursor position is
unaffected.
#include <curses.h>
main()
{
initscr();
insertln();
refresh();
endwin();
}
refresh() This function is used to update the physical terminal
screen from the window buffer and all changes made to that
buffer (via curses functions) will be written. If the
buffer size is smaller than the physical screen, then only
that part of the screen is refreshed, leaving everything
else unchanged.
#include <curses.h>
main()
{
initscr();
/* curses function call(s) here */
refresh();
endwin();
}
wrefresh() This function is identical to the refresh() function,
except that the refresh operation is performed on the named
window.
#include <curses.h>
main()
{
WINDOW *win;
initscr();
/* curses function call(s) here */
wrefresh(win);
endwin();
}
initscr() This function call must be present in all programs calling
the curses functions. It clears the physical terminal
screen and sets up the default modes. It should be the
first call to the curses functions when using the library
to initialize the terminal.
endwin() This function call should be present in any program using
the curses functions, and should also be the last function
call of that program. It restores all terminal settings to
their original state prior to using the initscr() function
call and it places the cursor to the lower left hand
portion of the screen and terminates a curses program.
-51-
52. attrset() This function allows the programmer to set single or
multiple terminal attributes. The call attrset(0)
resets
all attributes to their default state.
#include <curses.h>
main()
{
initscr();
attrset(A_BOLD);
/* sets character attributes to bold */
...
/* curses function call(s) here */
attrset(0);
/* resets all attributes to default */
refresh();
endwin();
}
attron() This function is used to set the named attribute of a
terminal to an on state.
#include <curses.h>
main()
{
initscr();
attron(A_BOLD);
/* sets character attribute to bold */
...
/* curses function call(s) here */
refresh();
endwin();
}
attroff() This function is the opposite of the attron() function
and
will turn off the named attribute of a terminal.
#include <curses.h>
main()
{
initscr();
attron(A_BOLD);
/* sets character attribute to bold */
...
/* curses function call(s) here */
attroff(A_BOLD);
/* turns off the bold character attribute */
refresh();
endwin();
}
-52-
53. standout() This function sets the attribute A_STANDOUT to an on state,
and is nothing more than a convenient way of saying
attron(A_STANDOUT).
#include <curses.h>
main()
{
initscr();
standout();
...
/* curses function call(s) here */
refresh();
endwin();
}
standend() This function, like standout(), is just a convenient way of
saying attroff(A_STANDOUT), meaning that the A_STANDOUT
attribute is set to an off state. Actually, this function
resets all attributes to the off state.
#include <curses.h>
main()
{
initscr();
standout();
...
/* curses function call(s) here */
standend();
/* end of attribute settings */
refresh();
endwin();
}
box() This function draws a box around the edge of the window.
One of its arguments is the horizontal character and the
other is the vertical character.
#include <curses.h>
main()
{
initscr();
box(stdscr, '-', '*');
/* draws a box around the stdscr */
/* horizontal characters are '-' and vertical characters are '*' */
refresh();
endwin();
}
Attribute Values: the following is a list of the terminal attributes that
may be set on or off using the curses library. It is important to note that
all of these attributes may not be available to the physical terminal,
depending upon the given terminal's characteristics.
-53-