8/3/2019 Lucent Guyz
1/27
Operating system
1. What are the features of RTOS which are responsible for its real
time nature?
reliability,predictability,
performance,
compactness, and
scalability.
2. What is the scheduling procedure in rtos or linux?Linux schedules the parent and child processes independently; theres no guaranteeofwhich one will run first, or how long it will run before Linux interrupts it and lets the
other process (or some other process on the system) run. In particular, none, part, orallof the ls command may run in the child process before the parent completes.2 Linuxpromises that each process will run eventuallyno process will be completelystarvedof execution resources.
You may specify that a process is less importantand should be given a lowerpriorityby assigning it a higher niceness value. By default, every process has a niceness ofzero.A higher niceness value means that the process is given a lesser execution priority;conversely, a process with a lower (that is, negative) niceness gets more executiontime.
3. How the scheduler gets a chance to run?Ans:) From RTC ISR
4. What are the resources shared across threads?
Ans:) all threads in a single program share the sameaddress space.Thismeans that if one thread modifies a location in memory (forinstance, a global variable),the change is visible to all other threads.This allows multiplethreads to operate
on the same data without the use interprocesscommunication mechanisms.
Each thread has its own call stack, however.This allows eachthread to execute different
code and to call and return from subroutines in the usual way.
8/3/2019 Lucent Guyz
2/27
fork a child process.The child process is initiallyrunning its parents program, with its parents virtual memory, file descriptors, and soon copied.The child process can modify its memory, close file descriptors, and thelikewithout affecting its parent, and vice versa.When a program creates another thread,though, nothing is copied.The creating and the created thread share the same
memoryspace, file descriptors, and other system resources as the original. If one threadchangesthe value of a variable, for instance, the other thread subsequently will see themodified
value. Similarly, if one thread closes a file descriptor, other threads may not read
5. How multiprocessing is different from multithreading?For some programs that benefit from concurrency, the decision whether to useprocesses or threads can be difficult. Here are some guidelines to help you decidewhich concurrency model best suits your program:n All threads in a program must run the same executable.A child process, on theother hand, may run a different executable by calling an exec function.n An errant thread can harm other threads in the same process because threads
share the same virtual memory space and other resources. For instance, a wildmemory write through an uninitialized pointer in one thread can corruptmemory visible to another thread.An errant process, on the other hand, cannot do so because each process has acopy of the programs memory space.n Copying memory for a new process adds an additional performance overheadrelative to creating a new thread. However, the copy is performed only whenthe memory is changed, so the penalty is minimal if the child process only readsmemory.nThreads should be used for programs that need fine-grained parallelism. Forexample, if a problem can be broken into multiple, nearly identical tasks, threadsmay be a good choice. Processes should be used for programs that need coarserparallelism.
n Sharing data among threads is trivial because threads share the same memory.(However, great care must be taken to avoid race conditions, as describedpreviously.)Sharing data among processes requires the use of IPC mechanisms.This can be morecumbersome but makes multipleprocesses less likely to suffer from concurrency bugs.
6. Mention different IPC techniques? What are the design
implications in each of them?
Semaphores
Message Queues
SignalsSockets
7. Which is the fastest IPC mechanism?
Ans: ) Shared memory
Shared memory is the fastest form of interprocess communication because all
8/3/2019 Lucent Guyz
3/27
processes share the same piece of memory. Access to this shared memory is as fastasaccessing a processs nonshared memory, and it does not require a system call orentry
to the kernel. It also avoids copying data unnecessarily.
Because the kernel does not synchronize accesses to shared memory, you mustprovideyour own synchronization. For example, a process should not read from thememory until after data is written there, and two processes must not write to thesamememory location at the same time.A common strategy to avoid these race conditions
is to use semaphores
8. What are sockets? Can we use them for inter-task
communication internal to a processor?
Yes VxWorks provides standard BSD socket calls, which allow real-time
VxWorkstasks and other processes to communicate in any combination with each
other over
the network.
Any task can open one or more sockets, to which other sockets can
be connected.
Data written to one socket of a connected pair is read, transparently, from
the other
socket. Because of this transparency, the two tasks do not necessarily know
whether they are communicating with another process or VxWorks task on
the
same CPU or on another CPU, or with a process running under some
other host
operating system.
A socketis a bidirectional communication device that can be used to communicatewithanother process on the same machine or with a process running on other machines.Sockets are the only interprocess communication well discuss in this chapter that
permit communication between processes on different computers. Internet programssuch as Telnet, rlogin, FTP, talk, and the World Wide Web use sockets.
When you create a socket, you must specify three parameters: communication style,namespace, and protocol.A communication style controls how the socket treats transmitted data and specifiesthe number of communication partners.When data is sent through a socket, it ispackagedinto chunks calledpackets.The communication style determines how these
8/3/2019 Lucent Guyz
4/27
packets are handled and how they are addressed from the sender to the receiver.n Connection styles guarantee delivery of all packets in the order they were sent. Ifpackets are lost or reordered by problems in the network, the receiver automaticallyrequests their retransmission from the sender.A connection-style socket is like a telephone call:The addresses of the senderand receiver are fixed at the beginning of the communication when the connection
is established.n Datagram styles do not guarantee delivery or arrival order. Packets may be lost orreordered in transit due to network errors or other conditions. Each packet mustbe labeled with its destination and is not guaranteed to be delivered.The systemguarantees only best effort, so packets may disappear or arrive in a differentorder than shipping.A datagram-style socket behaves more like postal mail.The sender specifies thereceivers address for each individual message.A socket namespace specifies how socket addresses are written. A socket addressidentifiesone end of a socket connection. For example, socket addresses in the localnamespaceare ordinary filenames. In Internet namespace, a socket address is composed ofthe Internet address (also known as an Internet Protocol address or IP address) of ahostattached to the network and a port number.The port number distinguishes amongmultiple sockets on the same host.A protocol specifies how data is transmitted. Some protocols are TCP/IP, the primarynetworking protocols used by the Internet; the AppleTalk network protocol; andthe UNIX local communication protocol. Not all combinations of styles, namespaces,
and protocols are supported.
9. How can we provide protected access to shared memory?
MutualExclusion
10. How can we avoid priority inversion?
Priority InheritancePriority Ceiling
11. What are semaphores? How binary semaphore is different
from mutex? A semaphore is used to control access to the criticalsection and a shared resource.
12. What are the different criteria to select different types of
semaphores?
13. What are spin locks and when are they used?
Ans:) Suppose that you write a thread function that executes a loop infinitely,performingsome work on each iteration.The thread loop, however, needs to be controlled by a
flag:The loop runs only when the flag is set; when the flag is not set, the looppauses.
Duringeach iteration of the loop, the thread function checks that the flag is set. Because theflag is accessed by multiple threads, it is protected by a mutex.This implementation
may be correct, but it is not efficient.The thread function will spend lots of CPU
8/3/2019 Lucent Guyz
5/27
whenever the flag is not set, checking and rechecking the flag, each time locking andunlocking the mutex.What you really want is a way to put the thread to sleep whenthe flag is not set, until some circumstance changes that might cause the flag to
become set.
14. What is the procedure to create process in linux?To spawn a new process, you first use fork to make a copy of the current process.Then
you use exec to transform one of these processes into an instance of the program youwant to spawn. When a program calls fork, a duplicate process, called the child
process, is created.The parent process continues executing the program from thepoint that fork was called. The child process, too, executes the same program from thesame place. Parent process id will be non zero and child process id will be Zero.A common pattern to run a subprogram within a program is first to fork the processand then exec the subprogram.This allows the calling program to continue executionin the parent process while the calling program is replaced by the subprogram in thechild process.
15. What is the use of kernel mode and user mode in RTOS
context?
16. What is the context of interrupts?17. Explain the interrupt mechanism with control flow.
CPU/processor will have Interrupt Input pin, peripheral controller
will have Interrupt output pin. Request line will connect both of
them. Whenever there is any interrupt signal by any device, the
peripheral control will present interrupt number to the interrupt
controller. On interrupt controller all of this interrupt ports will be
hardwired with priorities. CPU will use those interrupt number to
directly get the corresponding ISR. Normally all ISRs are
vectored in known location.
Whenever there is any interrupt signal, the CPU pushes current
instruction to the stack for the return to the previous instruction
execution point. Then CPU adds interrupt address as a offset to the
known memory location, where the ISR is located. This instruction
is loaded into instruction pointer.
18. Explain interrupt priorities.
All interrupt priorities are hardwired on interrupt controller.Interrupt controller can be on-chip with processor or external to the
processor. The main intention of priorities is to serve higher
priority interrupt incase of multiple interrupts raised.
19. What are soft and hard watchdogs? How are they used in
system design?
8/3/2019 Lucent Guyz
6/27
A watchdog timer is based on a counter that counts down from some initial value tozero. The embedded software selects the counter's initial value and periodically
restarts it. If the counter ever reaches zero before the software restarts it, thesoftware is presumed to be malfunctioning and the processor's reset signal is
asserted.
Soft watchdogs: Using monitor task.This scheme uses a task dedicated to the watchdog. This task wakes up at a regularinterval and checks the sanity of all other tasks in the system. If all tasks pass the
test, the watchdog is kicked. The watchdog monitor task runs at a higher priority
than the tasks it is monitoring.
The watchdog timeout can be chosen to be the maximum time during which allregular tasks have had a chance to run from their start point through one full loop
back to their start point again. Each task has a flag which can have two values,ALIVE and UNKNOWN. The flag is later read and written by the monitor. The
monitor's job is to wake up before the watchdog timeout expires and check thestatus of each flag. If all flags contain the value ALIVE, every task got its turn to
execute and the watchdog may be kicked. Some tasks may have executed several
loops and set their flag to ALIVE several times, which is acceptable. After kicking thewatchdog, the monitor sets all of the flags to UNKNOWN. By the time the monitortask executes again, all of the UNKNOWN flags should have been overwritten with
ALIVE. Figure 3 shows an example with three tasks.
http://i.cmpnet.com/embedded/gifs/2000/0011/0011feat4fig3.gifhttp://i.cmpnet.com/embedded/gifs/2000/0011/0011feat4fig3.gif8/3/2019 Lucent Guyz
7/27
Hardware Implementation:
A simple example is shown in Listing 1. Here we have a single infinite loop thatcontrols the entire behavior of the system. This software architecture is common in
many embedded systems with low-end processors and behaviors based on a singleoperational frequency. The hardware implementation of this watchdog allows the
counter value to be set via a memory-mapped register.
Listing 1: Kicking the dog
uint16 volatile * pWatchdog =
(uint16 volatile *) 0xFF0000;
main(void)
{hwinit();
for (;;){
*pWatchdog = 10000;read_sensors();
control_motor();
display_status();}
}
Suppose that the loop must execute at least once every five milliseconds. (Say themotor must be fed new control parameters at least that often.) If the watchdog
timer's counter is initialized to a value that corresponds to five milliseconds ofelapsed time, say 10,000, and the software has no bugs, the watchdog timer will
never expire; the software will always restart the counter before it reaches zero.
20. What is the trigger to enter kernel mode?
Ans:) . A process invokes a system call. The CPU executing the process signals an exception, which is some unusual condition
such as an invalid instruction. The kernel handles the exception on behalf of the
process that caused it. A peripheral device issues an interrupt signalto the CPU to notify it of an event suchas a request for attention, a status change, or the completion of an I/O operation. Each
interrupt signal is dealt by a kernel program called an interrupt handler. Since
peripheral devices operate asynchronously with respect to the CPU, interrupts occur atunpredictable times.
21. Explain virtual memory concept.
22. Explain paging mechanism.
8/3/2019 Lucent Guyz
8/27
Networking
1. Explain end to end packet flow over a network.
2. Explain layer 2 forwarding.
3. What is ARP, proxy etc...
4. Explain Ethernet and ATM headers.Ans: Preamble | SFD | DMA | SMA | Length/Type | data | FCS
5. How Ethernet is different from ATM.
6. Explain virtual LAN.7. Why 0 and 4095 are reserved in VLAN.
Ans: 4095 is a Discard VLNS
8. What is VLAN stacking?
9. How forwarding decision table is maintained for each vlan.
10. Explain routing.
8/3/2019 Lucent Guyz
9/27
11. Explain IP header.
12. Explain static and dynamic routing protocols.
13. Explain ospf and rip protocols.
14. Explain RIB.
15. How a layer 2/3 switch can decide whether to route apacket or to forward it.
16. How the packet is sent when the destination host is not in the
local network?
17. What happens when default gateway is not configured?
18. What is network byte order?
Big endian order (I Gusess, should be confirmed by google)
19. Explain TCP and UDP headers.
20. What are the uses of TCP?21. If the packet length is small, how it will be handled?
22. What is the basis for ATM?
23. PC-PC packet transmission (eg FTP)?
24. Explain TCP,UDP? Difference?
25. Difference RIP and OSPF? (He expected Classful
masking)
26.
8/3/2019 Lucent Guyz
10/27
C Programming and data structures
1. What are the differences between a macro and inline?
Macro doesnt check datatype check errors.
Inline functions throws errors if there is mismatch of
datatypes in function arguments.
2. What is a volatile variable?The usual four examples of volatile objects are:
An object that is a memory-mapped I/O port
An object that is shared between multiple concurrent processes
An object that is modified by an asynchronous signal handler
An automatic storage duration object declared in a function
that calls
setjmp, and whose value is changed between the call to setjmp
and acorresponding call to longjmp
3. Are all global variables volatile?
No
4. What is a static function?
Function has file Scope. It cant be called from outside the
file
5. What is a function pointer and what are its uses?
Callback functions, Signals, ISR
6. Explain union of structures.7. What are the disadvantages of BST?
8. What are the design criteria for trees?
9. Explain balanced trees.
10. What are the different regions in memory?
11. Lifetime and scope of the variables.
8/3/2019 Lucent Guyz
11/27
Auto block scope, destroyed after block exit
extern program scope, memory persists untill the program
ends
static scope to the block, memory persists untill the program
endsregister processor register, local to block
12. What is sizeof().
Unary operator
1. Write a program to swap adjacent elements of a singly linked
list.
void swap_adjacent_elements1(SL *del_node)
{
SL *node = head, *prev = head;printf("void swap_adjacent_elements1(SL *del_node)\n");
while(node->next)
{
if(del_node == head)
{
SL *temp = head->next->next;
node->next->next = head;
head = node->next;node->next = temp;
break;
}
else if(node == del_node)
{
SL *temp = node->next->next;
prev->next = node->next;
prev->next->next = node;
node->next = temp;break;
}
prev = node;
node = node->next;
}
8/3/2019 Lucent Guyz
12/27
}
2. Write a program to delete an element of linked list without
traversing and not using temporary pointer.
Node *temp = NULL;
if(node == head){
*temp = head;
head = node->next;
}
else if(node->next != NULL)
{
memcpy(&(node->data),&(node->node->next-
>data),sizeof(node->data));memcpy(node->next,node->next->next,sizeof(Node));
}
if(temp !=NULL)
{
free(temp);
temp = NULL;
}
if(node && node->prev && node->next)
{
node->prev->next = node->next;
node->next->prev = node->prev;
}
else if(node == head)
{
head = node->next;
node->next->prev = NULL;}
elseif(node->next == NULL)
{
node->prev->next = NULL;
}
8/3/2019 Lucent Guyz
13/27
free(node);
node = NULL;
3. Write a program to store the order of elements coming out of
an infinite stream [1, N] without repetitions.
4. Write an efficient program to search an element in 2D matrixwhich is sorted both horizontally and vertically.
For example the 2D array could look like the following
1 4 5 6
2 5 7 9
search diagonally.
diag 1 = 1
diag2 = 2,4
?.
for example
given the number 7 we take the bounds of each diagonal and
check wether the number will fall in that range else move
farward.
here diagonal selection is sequential but the number search isbinary.
sort on the last column
suppose
n*n matrix
low= 0;
high =n-1;
while ( low!=high )
{
mid = floor [( low + high )/2];
8/3/2019 Lucent Guyz
14/27
if(a[mid][n-1]==item)
return
if(a[mid][n-1]>item)
high = mid;
if(a[mid][n-1]left_link,node2->left_link);
if(flag1 == 1)
{
return 1;
}
flag2 = compare(node1->right_link,node2->right_link);if(flag2 == 1)
{
return 1;
}
printf("Success till end\n");
return 0;
}
else if(!node1 && !node2)
{return 0;
}
else
{
return 1;
8/3/2019 Lucent Guyz
15/27
}
}
6. Write a program to reverse a string without using temporary
char array.
main(){
char str[20] = "satish";
int i = 0,n = strlen(str)-1;
while(i
8/3/2019 Lucent Guyz
16/27
}
13. Write a program to remove redundant dots in a string without
using temp string.
/*The following is easy to remember*/
main(){
char a[] = "sat...pqr...st.uv.yyy...z.";
int i = 0,j = 0;
while(a[i])
{
if(a[i] == '.' && a[i] == a[i+1])
{
i++;}
else
{
a[j] = a[i];
j++;
i++;
}
}a[j] = '\0';
printf("%s",a);
getch();
}
------------------------------------------
main()
{
char a[] = "sat..in..dia.....over...alu...bike.create..onetwo";
int i = 0, j =0, flag =0;while(a[i])
{
if(a[i] == '.')
{
if(flag == 0)
8/3/2019 Lucent Guyz
17/27
{
a[j++] = a[i];
flag = 1;
}
i++;}
else
{
a[j++] = a[i++];
flag = 0;
}
}
a[j] = '\0';printf("%s",a);
getch();
}
14. Write state machine program.
typedef enum sat_IDLE_DAY_STATES_NUM
{
idle_state =0,sleepy_mode,
funny_mode,
sad_mode,
busy_mode,
NUM_STATES
}sat_IDLE_DAY_STATES_NUM;
typedef enum sat_IDLE_DAY_EVENTS_NUM
{ignore_evt = 0,
sat_day_beginning_alarm,
sat_phone_rings,
sat_pending_work_reminder,
emergency_at_home,
8/3/2019 Lucent Guyz
18/27
Television_started,
NUM_EVENTS
}sat_IDLE_DAY_EVENTS_NUM;
typedef struct sat_fsm_info{
sat_IDLE_DAY_EVENTS_NUM prev_evt;
sat_IDLE_DAY_EVENTS_NUM curr_evt;
sat_IDLE_DAY_STATES_NUM prev_state;
sat_IDLE_DAY_STATES_NUM curr_state;
}sat_fsm_info;
void wake_up(sat_fsm_info*);void ignore(sat_fsm_info*);
void shut_alarm(sat_fsm_info*);
void shut_phone(sat_fsm_info*);
void offhook(sat_fsm_info*);
void mute(sat_fsm_info*);
void takeup_act(sat_fsm_info*);
//Sat FSM - idle day
void (*sat_FSM [NUM_STATES] [NUM_EVENTS])(sat_fsm_info*) =
{
{wake_up,offhook,shut_alarm,ignore},
{shut_phone,offhook,mute,offhook},
{wake_up,ignore,shut_alarm,takeup_act},
{wake_up,ignore,shut_alarm,ignore},
{wake_up,ignore,shut_alarm,ignore},
};
main()
{
int evt;
sat_fsm_info *sat_fsm_data =
(sat_fsm_info*)malloc(sizeof(sat_fsm_info));
8/3/2019 Lucent Guyz
19/27
memset(sat_fsm_data,0,sizeof(sat_fsm_info));
do
{
printf("Which event is going to happen and tell me your current
state\n");printf(" CURRENT EVENT \n");
printf("1::Wake-up Alarm \n");
printf("2::Phone Ringing \n");
printf("3::Pending Work Reminder \n");
printf("4::Emergency at home \n");
printf("5::Television started \n");
scanf("%d",&evt);
sat_fsm_data->prev_evt = sat_fsm_data->curr_evt;
sat_fsm_data->prev_state = sat_fsm_data->curr_state;
sat_fsm_data->curr_evt = evt;
printf("Current state is %d Cureent evt is %d\n",sat_fsm_data-
>curr_state,evt);
sat_FSM[sat_fsm_data->curr_state][evt](sat_fsm_data);
}while(evt!=0);//getch();
}
void wake_up(sat_fsm_info *data)
{
printf("We are in wake_up state\n\n\n\n\n");
data->curr_state=0;
}
void ignore(sat_fsm_info *data){
printf("We are in ignore state\n\n\n\n\n");
}
void shut_phone(sat_fsm_info *data)
{
8/3/2019 Lucent Guyz
20/27
printf("We are in shut_phone state\n\n\n\n\n");
}
void offhook(sat_fsm_info *data)
{
printf("We are in offhook() handler\n\n\n\n\n");data->curr_state = busy_mode;
}
void mute(sat_fsm_info *data)
{
printf("We are in mute state\n\n\n\n\n");
}
void shut_alarm(sat_fsm_info *data)
{printf("We are in shut_alarm state\n\n\n\n\n");
}
void takeup_act(sat_fsm_info *data)
{
printf("We are in takeup_act state\n\n\n\n\n");
}
15. Write a program for avl tree.
16. Write a efficient program to transmit information ofdifferent things present in a box.
17. Write a program to count number of 1s in a byte.
main()
{
int num = 0;
int x = num,count=0;
while(x)
{
if(x & 0x1){
count++;
}
x >>=1;
}
8/3/2019 Lucent Guyz
21/27
printf("count=%d\n",count);
getch();
}
18. Write a program to reverse an integer.#include
#include
main()
{
int temp,num,rnum=0;
printf("\nEnter the decimal number , num = ");
scanf("%d",&num);
printf("\n The Decimal Number entered is = %d , ",num);while(num>0)
{
temp = num % 10;
rnum = 10 * rnum + temp;
num = num /10;
}
printf("\n Reverse of Decimal num = %d ",rnum);
getch();}
19. Write a program to print A for 1, Bfor 2, AA for 27 and
so on based on the integer input.
#define MAX_ALPHABET 26
#define ASCII_OFFSET 64
main()
{
int i=0,j=0,k=0;printf("Enter no \n");
scanf("%d",&i);
j=i/MAX_ALPHABET;
k=i%MAX_ALPHABET;
if (j){
8/3/2019 Lucent Guyz
22/27
printf("\n%c",j+ASCII_OFFSET);
printf("%c",k+ASCII_OFFSET);
}else{
printf("\n%c",k+ASCII_OFFSET);
}getch();
}
20. Write a macro to multiply two numbers.
ANS:) #define MUL(a,b) ((a) * (b))
21. Write a program to implement printf.
22. Write a program to print ; using it only once.
23. Find redundant value in a linked list?
void find_redundant(){
SL *temp1 = head;
int flag = 0;
while(temp1)
{
SL *temp2 = temp1->next;
while(temp2)
{if(temp1->data == temp2->data)
{
flag = 1;
break;
}
temp2 = temp2->next;
}
if(flag == 1)
{printf("found\n");
break;
}
temp1 = temp1->next;
}
8/3/2019 Lucent Guyz
23/27
}
void remove_redundant()
{
SL *node1 = head;SL *node2 = NULL;
SL *prev = NULL;
while(node1)
{
node2 = node1->next;
prev = node1;
while(node2)
{if(node1->data == node2->data)
{
prev->next = node2->next;
free(node2);
node2 = prev;
}
prev = node2;
node2 = node2->next;}
node1 = node1->next;
}
}
24. In BST, find a node , if data is not found return next
higher variable?
25. In BST, find a node, if data is found return data+1?
26. Implement dictionary using tree?
27. Find out middle node in a linked list?void find_middle_node()
{
SL *temp1=head,*temp2 = head;
int count = 0;
while(temp1 && temp2)
8/3/2019 Lucent Guyz
24/27
{
temp1 = temp1->next;
if(temp2->next)
{
temp2 = temp2->next->next;}
else
{
break;
}
count++;
}
printf("the mid node = %x data= %d, position=%d\n",temp1,temp1->data,count);
}
28. BST Definition?
29. Recursion eg?
30. disadvantages of recursion in Embedded systems?
31. Explain pointer to pointer with an example?
32. reentrant functions?
Output for code snippets
1 char a[]={1,2,3,4};
int *p;
p=(int *)a;
printf(%d\n,*p);
Ans:) based on little/big end machine
2. int *p=0;
p++;
8/3/2019 Lucent Guyz
25/27
printf(%d\n,p);
Ans:) 4
3. char a[]=print;for(int i=0;i
8/3/2019 Lucent Guyz
26/27
Design and debugging
1. Linked list corruption.
2. Stack corruption.
3. Heap corruption.
4. Crash in an inline function.
5. Inter card communication.6. Protected shared memory access.
7. Zombie state.
8. Memory utilization.
9. Race over condition.
10. Deadlocks.
Product oriented
1. Network processor.
2. Redundant Cpu design.
3. Fault tolerant system.
4. Traffic loss.
5. Packet switching.
6. Protocol stack.
7. Address mappings over different n/w technologies.
8. Redundant traffic paths.
9. IMA.10. Data path
8/3/2019 Lucent Guyz
27/27
C++ programming
Top Related