I believe they are looking for a diagram of copy on write here.
Userspace threading is refered to N:1 threading. Within this moodel a process with N threads will map to a single kernel process. Hence N:1. This model requires little to no kernel support but is significant userspace code. The benefit of user space threads is that context switches are nearly free, as the application itself can decide what therad to run and when, without invoking the kernel. The downside is that, as there is only a single kernel entity backing the N threads, this model cannot utilize mutiple procesors and thus is unable to provide true parallelism.
A detached thread is one that does not require its return status to be acknowledged. In this case we do not have to wait for the thread to complete and we do not have to use pthread_join() to clean up after it.
A non-detached thread is one that does require its return status to be acknowledged. This means we can wait for its completition using pthread_join()
Thread-safe means that the function may be safely invoked within a multithreaded context.
Reentrant means that the function may be safely invoked from a async-signal context.
A Spurious wakeup describes a complication in the use of a condition variable. The complication doesn't necessarily mean the data we were waiting on is now available.
In order to fix this we can replace the if with a while:
while(room_available == false) {
pthread_cond_wait(&room, &mutex);
}The thread will not exit cleanly. The only cancelation point within the snippet provided is pthread_cond_wait(), since no cleanup handler is provided it is safe to assume that on cancellation the mutex will remain in a locked state.
Register a cleanup handler to unlock the mutex.
pthread_cleanup_push(pthread_mutex_unlock, mutex);
pthread_mutex_lock(&mutex);
while(room_available == false) {
pthread_cond_wait(&room, &mutex);
}
pthread_cond_signal(&data);
pthread_mutex_unlock(&mutex);
pthread_cleanup_pop(0);Hello!
Received 1
Hello!
Received 2
Hello!
Received 3
The wait system call forces the parent process to wait for the child process to complete. If the wait was taken away the parent process may end before the child has finished executing, this results in the child becoming a zombie.
surface * tracks per suerface * sector per track * bytes per sector
6 * 2000 * 800 * 512 = 4915200000 bytes
bytes read in 1 s = tracks in 1 s * bytes per track
= (RPM / 60) * sectors per track * bytes per sector
= (5000 / 60) * 800 * 512
= 34133333.3333
time for 0.5 revolutions = time for 1 revolution / 2
= (60 / RPM) / 2
= (60 / 5000) / 2
= 0.006s
transfer_time = time taken for one sector to pass r/w head
= 60 / (RPM * sectors per track)
= 60 / (5000 * 800)
= 0.000015s
time to read/write 1 sector = seek time + rotational latency + transfer time
= 0.006 + 0.006 + 0.000015
= 0.012015s
What percentage of the time calculated in Part III that is spent actually reading/writing the sector?
percentage = 100 * transfer time / total time
= 100 * 0.000015 / 0.012015
= 0.1248%
Fine-grained: stripe each file over all disks
- high throughput for the file
- limits transfer to 1 file at a time
coarse-grained: stripe each file over only a few disks
- Limits throughput for 1 file
- allows concurrent access to multiple files
Raid 4 - Blocked striped and dedicated Parity Disk.
- Minimum of 3 disks. 2 for data 1 for parity
- Good random reads as blocks are striped
- Bad random writes as for every write it has to write to a single parity disk
Raid 5 - Blocks striped and distributed Parity.
- Minimum 3 disks
- Good performance as blocks are striped
- Good redundancy as the parity is distributed
RAID5 supports parallel independant writes. RAID5 is able to do this due to the parity being distributed across disks. RAID4 cannot do this as it cannot do multiple writes to the Parity drive at the same time.
- Universal Serial Bus
- Small Computer Systems Interface
- Integrated Drive Electrionics
- Do not used fixed-sized directory entries and store the filename within the directory entry.
- Keep filenames in a heap and the end of a directory and have the directory entries create pointers to the heap.
- Judy enters her username and password
- The entered password is hashed and compared with an entry within /etc/shadow
- If the password is correct her shell is launched, otherwise she is denied access
The permissions on the file will be determined based of the effective UID and GUID of the the process.
foobar, owned by user and group root has permissions: owner: read/write group: execute read everybody: execute
Along with this the sticky bit is set, this means it will be launched under the user account of the person who owns it. In this case root.
When Mary executes foobar her UID and GUID will be the real user id of the process, however the effective UID and GUID will be root's UID and GUID due to the sticky bit.
In order to create a file as Mary we must set the effective user id to the real user id, set the umask accordingly to read and write and create the file.
foobar should drop privileges permanently as soon as they are no longer required in order to insure security across the system. Effective Ids will be inherited across exec and child processes we do not want a user getting processes running as root by mistake.
We can drop privileges by using setuid
- Allow ordinary users to execute mp3player
- Allow mp3player to serve as an entry point to mp3player_t
- Allow users in the role user_r to enter mp3player_t
A vulnerability which no patch exists for is known as a "zero-day".
SELinux will not prevent zero-days however it can lessen there effects. By using SELinux we limit the access levels of applications, thus an exploited application only has a certain access level. This prevents the attacker from executing nasty instructions.
In an ideal word we want to have all our services seperated from each other. Most failures are caused due to application bugs. We do not want a single application to take down all our services running on the same box. In order to prevent this we split services off into their own dedicated isolated operating systems.
However doing this with physical machine is difficult and expensive to manage. So we consolidate all our services down into virtual machines running on one powerful box which is acting as a hypervisor. As a result we get all our services on one box in isolated environments, this means one service cannot take down another.
A virtual appliance is an application with its run-time environment and an operating system bundled together and shipped as a virtual machine. This saves installation headaches.
- Executes the priviledge operation
- Emulates what the hardware would do
A virtual disk is implemented as a file on the host operating system.
Not all sensitive instructions are privileged. pushf operates differently when executed in priviledged mode and when executed in user mode.
If executed in virtual kernel mode it will not trap and it will not be emulated correctly.
There are two approaches to solving this:
- Binary translation - Scan the instructions if a sensitive instruction is found replace it with a call to the hypervisor.
- VT-x - The processor notifies the hypervisor when a set of events occur.
- An application running on a guest operating system invokes a system call by generating a software interrupt.
- The trap goes to the host operating system.
- The type-2 hypervisor was registered itself as a debugger with the host operating and is passed control by the host in response to the trap.
- The hypervisor determines that the trap was caused by code executing in virtual mode.
- The hypervisor hands control to the system call handling code in the guest operating system.
- The guest operating system executes the system call









