- About the Project
- Signals
- Used Functions
- Bitwise and ¿WHY IS IMPORTANT?
- Building the Thing
- Last Recommendations and Helpful Repositories
Minitalk is a project from the second ring of the common core in the 42 cursus, focusing on sending messages from the client to the server using UNIX signals. This approach allows us to develop essential skills in signal handling and bitwise operations, crucial in software development.
A signal is a "notification" that one process can send to another process; UNIX signals are received and processed immediately. A common example is CTRL + C, which sends the SIGINT (INTERRUPT SIGNAL) to halt the process.
Signal Name | Number | Purpose |
---|---|---|
SIGINT | 2 | Interruption (Ctrl-C) |
SIGFPE | 8 | Floating-point error (e.g., division by zero) |
SIGPIPE | 13 | Attempt to write to a broken connection |
SIGALRM | 14 | Timer expiration |
SIGUSR1 | 16 | Customizable by the programmer |
SIGUSR2 | 17 | Customizable by the programmer |
For Minitalk, we focus on SIGUSR1 and SIGUSR2 for interaction between programs.
- Sending and Handling Signals in C (kill, signal, sigaction)
- Communicating between processes using signals.
-
signal(signalname, signalhandler)
:- This function is used to capture signals. It takes two parameters: the signal with which it will interact and the signal handler. The signal handler defines the action to be taken upon capturing the signal. The handler can be a user-created function or a specific action. In the case of a custom function, the prototype would be void handler(int signal), where signal is the number or name of the captured signal.
-
kill(signalname, pid)
:- Allows us to send a signal to a specific process identified by its PID (Process Identifier). It takes two parameters: the signal we want to send and the PID of the target process.
-
getpid()
:- Retrieves the subprocess number of the currently executing program.
-
usleep(microseconds)
:- The usleep function instructs the program to pause for a specified duration (in microseconds) before processing the next signal. For a clearer understanding of the program's operation, especially during testing, the sleep function can be used instead. It performs the same function as usleep but operates in seconds, making it easier to observe how signals interact.
DISCLAIMER: It is recommended to interpret signals as quickly as possible since a delay in presenting a word can impact project performance.
The term "bitwise" pertains to operations involving the manipulation of bits. In this context, working with data at the bit level proves advantageous, as the information transmitted through signals is compressed. This enables quicker and more efficient interpretation, ultimately contributing to the development of an optimized program that demands less storage space.
For a comprehensive understanding of bitwise operations, i recommend watching this informative video: Bitwise operators.
// Function to send bits to the server
void sendbits(int pid, char *str, int len)
{
int i;
int shift;
i = 0;
// Check if PID is valid
if (pid == 0)
return;
// Check if the message is empty
if (*str == 0)
{
printf("ERROR: Invalid message (empty)\n");
return;
}
// Iterate through each character in the string
while (i < len)
{
shift = 7;
// Iterate through each bit of the character
while (shift >= 0)
{
// Send signal based on the bit value
if ((str[i] >> shift) & 1)
kill(pid, SIGUSR1);
else
kill(pid, SIGUSR2);
shift--;
usleep(100); // Pause for signal processing
}
i++;
}
}
void signalhandler(int signal)
{
static int bit; // Track the current bit position in the received byte
static unsigned char letter; // Store the reconstructed ASCII character
int number; // Represent the bit value (0 or 1) based on the received signal
if (signal == SIGUSR1)
number = 1;
else
number = 0;
letter = (letter << 1) + number; // Update the ASCII character by shifting bits and adding the new bit
bit++;
// If a complete byte (8 bits) has been received
if (bit == 8)
{
write(1, &letter, 1); // Print the reconstructed ASCII character to the standard output
letter = 0; // Reset the letter variable for the next byte
bit = 0; // Reset the bit counter for the next set of signals
}
}
Improve your understanding of the Minitalk project by learning manual conversion between integer and binary. This key knowledge will allow you to better understand bitwise operations. Remember that shifting right is like dividing by 2, and shifting left is like powering by 2. These concepts are essential not only for Minitalk, but also for future projects that involve bit manipulation.
Special acknowledgment to those who aided in unraveling the complexities of Minitalk:
Their contributions have been instrumental in my understanding of Minitalk, and credit is duly given to them.