"Operating System Principles" Experimental Report 2

1. The purpose of the experiment
(1) Understand the concept of operating system threads and application programming process;
(2) Understand the concept of thread synchronization and programming;

2. Experiment content
(1) Use fork function to create a pair of parent and child processes in Ubuntu or Fedora environment, and output their own process number and prompt message string respectively.
(2) Use pthread_create function to create 2 threads A and B in Ubuntu or Fedora environment. Thread A uses a while loop to sequentially output natural numbers from 1 to 1000 on the screen; thread B uses a while loop to sequentially output natural numbers from 1000 to 1 on the screen. To avoid output too fast, output a number every 0.5 seconds.
(3) In windows environment, use high-level language programming environment (limited to VS environment or VC environment) to call CreateThread function to realize the function of (2).
(4) In windows environment, use high-level language programming environment (limited to VS environment or VC environment) to call CreateThread function and related synchronization functions to simulate the realization of "producer-consumer" problem.
(5) In windows environment, use high-level language programming environment (limited to VS environment or VC environment) to call CreateThread function to achieve "concurrently draw circles and squares". The center, radius, color, center of the square, side length, color and other parameters of the circle are determined by yourself. It is recommended to take 720 points on the boundary of the circle and the square. In order to visually show the drawing process, sleep for 0.2 seconds to 0.5 seconds after each point is drawn.

3. Experimental process
(1) Experimental step
1) Fork function to create a parent-child process
1. Open a text editor on ubuntu and write c program (problem1.c)
2. Core code

1.	void main()  
2.	{
    
       pid_t pid;        
3.	    fprintf(stdout,"I am the first process, my pid is %d, my parent pid is %d\n",getpid(),getppid());    
4.	    pid=fork();  
5.	    if(0==pid)  
6.	        fprintf(stdout,"I am the child process, my pid value is %d, but my real pid is %d, my parent pid is %d\n",pid,getpid(),getppid());  
7.	    else  
8.	        fprintf(stdout,"I am the parent process, my child pid value is %d, my real pid is %d, my parent pid is %d\n",pid,getpid(),getppid());   
9.	}  

3. Line 3 requires the output of the pid of the current process and the pid of its parent process. The pid in line 4 is the return value of the fork() function. Lines 6 and 7 respectively output information about different processes at runtime (getpid() ,getppid() returns the pid of the process and its parent process respectively)
4. Compile the program on the terminal and output the result
#gcc problem1.c
#./a.out
5. Analysis result

2) The pthread_create function creates 2 threads (problem2.c)
1. Open the text editor on ubuntu and write the c program
2. Core code

10.	int main()
11.	{
    
    
12.	    pthread_t tips1;
13.	    pthread_t tips2;
14.	    int hThread1 = pthread_create(&tips1, NULL, print1, NULL);
15.	    int hThread2 = pthread_create(&tips2, NULL, print2, NULL);
16.	    if (hThread1 != 0)
17.	    {
    
    
18.	        printf("hThread1 err");
19.	    }
20.	    else if (hThread2 != 0)
21.	    {
    
    
22.	        printf("hThread2 err!");
23.	    }
24.	    void *result1;
25.	    void *result2;
26.	    pthread_join(tips1, &result1);
27.	    pthread_join(tips2, &result2);
28.	    return 0;
29.		} 
  1. pthread_create(,,,) creates a thread, the first parameter is a pointer to the thread identifier, the second parameter is used to set thread attributes, the third parameter is the starting address of the thread running function, and the last parameter is the running function Parameters. Return value: If successful, it returns 0, otherwise it returns the error number.
    pthread_join(,) is used to wait for the end of a thread. The first parameter is the identifier of the thread being waited for, and the second parameter is a user-defined pointer that can be used to store the return value of the thread being waited for. This function is a thread blocking function. The function that calls it will wait until the waiting thread ends. When the function returns, the resources of the waiting thread are recovered. If the execution is successful, it will return 0, if it fails, it will return an error number.
    4. Compile the program on the terminal and output the result
    #gcc problem1.c -lpthread
    #./a.out
    5. Analysis result
    3) VS environment realizes the function of (2)
    1. Open VS write c program (problem3.cpp)
    2. Core code
30.	int main()
31.	{
    
    
32.	    HANDLE hThread[2];
33.	    //创建线程,并调用函数打印输出
34.	    hThread[0] = CreateThread(NULL, 0, print1, (LPVOID)1000, 0, NULL);
35.	    hThread[1] = CreateThread(NULL, 0, print2, (LPVOID)1, 0, NULL);
36.	    //等待所有线程结束
37.	    WaitForMultipleObjects(2, hThread, TRUE, INFINITE);
38.	
39.	    CloseHandle(hThread[0]);
40.	    CloseHandle(hThread[1]);
41.	
42.	    return 0;
43.	}
  1. In C/C++, you can create threads in the process through the CreateThread function. The specific format of the function is as follows:
HANDLE CreateThread(
                    LPSECURITY_ATTRIBUTES lpThreadAttributes,
                    DWORD dwStackSize,
                    LPTHREAD_START_ROUTINE lpStartAddress,
                    LPVOID lpParameter,
                    DWORD dwCreationFlags,
                    LPDWORD lpThreadID
                   );

The meaning of the parameters are as follows:
lpThreadAttrivutes: pointer to SECURITY_ATTRIBUTES, used to define the security attributes of the new thread, generally set to NULL;
dwStackSize: the size of the thread stack allocated in bytes, the default value is 0;
lpStartAddress: point to a thread Function address. Each thread has its own thread function, which is the specific execution code of the thread;
lpParameter: the parameters passed to the thread function;
dwCreationFlags: indicates the running status of the created thread, where CREATE_SUSPEND means suspend the currently created thread, and 0 means Execute the currently created process immediately;
lpThreadID: return the ID number of the newly created thread;
if the function call is successful, return the handle of the new thread, call the WaitForSingleObject function to wait for the end of the created thread. The format of the function is as follows:
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
The meaning of the parameters is as follows:
hHandle: the handle of the specified object or time;
dwMilliseconds: the waiting time, in milliseconds. When the waiting time exceeds the waiting time, this function returns. If the parameter is set to 0, the function returns immediately; if it is set to INFINITE, the function does not return until there is a signal. 4. Debug and run the program
5. Analyze the results

4) VS environment simulation to achieve "producer-consumer" problem
1. Open VS to write c program (problem4.cpp)
2. Concurrent producer-consumer model of threads: 1. Two processes operate on the same memory resource , One is the producer and the other is the consumer. 2. The producer fills the shared memory resource with data, and if the area is full, it waits for the consumer to consume the data. 3. The consumer fetches data from the shared memory resource, and if the area is empty, it waits for the producer to fill in the data. 4. The data filling behavior of the producer and the data consumption behavior of the consumer cannot occur at the same time. ,
3. core code

44.	DWORD WINAPI producer(LPVOID v)
45.	{
    
    
46.		int item;
47.		while (true)
48.		{
    
    
49.			item = produce_item();
50.			empty--;
51.			if (empty < 0)
52.				empty++;
53.			else if (mutex > 0) 
54.			{
    
    
55.				mutex--;
56.				insert_item(item); 
57.				full++;
58.				mutex++;
59.			}
60.			Sleep(2000);
61.		}
62.		return 1;
63.	}
64.	
65.	DWORD WINAPI consumer(LPVOID v)
66.	{
    
    
67.		int item;
68.		while (true)
69.		{
    
    
70.			full--;
71.			if (full < 0)
72.				full++;
73.			else if (mutex > 0)
74.			{
    
    
75.				mutex--;
76.				item = remove_item();
77.				empty++;
78.				mutex++;
79.			}
80.			Sleep(2000);
81.		}
82.		return 1;
83.	}
  1. DWORD WINAPI producer (LPVOID v), DWORD WINAPI consumer (LPVOID v) means that the two threads of producer and consumer can run effectively and concurrently through PV operation; the two threads are mutually exclusive in the buffer, and the semaphore mutex=1( Initial value); Use full and empty to represent the buffer storage; insert_item(item), remove_item() represent storing and removing data to the buffer.
    4. Debug and run the program
    5. Analyze the results
    5) VS environment to draw
    circles and squares concurrently 1. Open the VS to write c program (problem5.cpp), first use EasyX to create the canvas
    2. Core code
	DWORD WINAPI circle(LPVOID n)
85.	{
    
    
86.	    double r = 200.0,x0=250.0,y0=250.0;//半径与圆心
87.	    int x1,x2,y;
88.	    for (y=50;y<=450;y+=6)
89.	    {
    
    
90.	        double yy = sqrt(r*r-(y-y0)*(y-y0));
91.	        x1 = x0 - yy;
92.	        x2 = x0 + yy;
93.	        outtextxy(x1,y,c);
94.	        Sleep(100);
95.	        outtextxy(x2,y,c);
96.	        Sleep(100);
97.	    }
98.	    return 0;
99.	}
100.	
101.	//画方
102.	DWORD WINAPI tangle(LPVOID n)
103.	{
    
    
104.	    int mx = 540, my = 50;//左上角
105.	    for (; my < 300; my+=10)
106.	    {
    
    
107.	        outtextxy(mx,my,c);
108.	        Sleep(100);
109.	    }   
110.	    for (; mx < 940; mx += 10)
111.	    {
    
    
112.	        outtextxy(mx, my, c);
113.	        Sleep(100);
114.	    }
115.	    for (; my > 50; my -= 10)
116.	    {
    
    
117.	        outtextxy(mx, my, c);
118.	        Sleep(100);
119.	    }
120.	    for (; mx > 540; mx -= 10)
121.	    {
    
    
122.	        outtextxy(mx, my, c);
123.	        Sleep(100);
124.	    }
125.	    return 0;}

3. Output the sides of circles and rectangles one by one in the form of points on the canvas. By using the outtestxy() function on EasyX, it is more convenient to use the coordinates of the points on the circle and rectangle.
4. Debug and run the program
5. Analyze the results

(2) Resolving errors and optimizing
1. The operation process is wrong, and the corresponding file cannot be found when the terminal compiles the C language program. Because I saved the c program on the desktop, the default location of the terminal is the home directory, so I can't find it, just move the file to the home directory.
2. Special syntax error, error when outputting program running result. The command is entered incorrectly, it should be #./a.out, do not ignore the ".".
3. Compile error, problem2.c cannot be compiled. Pay attention to adding the -lpthread parameter when compiling to call the static link library. Because pthread is not the default library of the Linux system.
Insert picture description here
4. Special grammatical errors,
Insert picture description here

When the call to CloseHandle is successful, the reference count of the related kernel object is decremented by one. This function does so much work. It doesn't really close the kernel object, it just decrements the count by 1, and CreateThread() returns the correct value.

5. Operation error, the number of producer and consumer access is incorrect. The two PV operations are not arranged in a reasonable order, resulting in errors. Draw a picture to analyze the sequence of execution of PV operations.
Insert picture description here

6. Operation error, the shape of the circle and rectangle is wrong. In the beginning, EasyX was not used to draw pictures, and spaces were used to determine the coordinates, which caused confusion in the spaces of circles and rectangles, resulting in incorrect shapes.
Insert picture description here

After creating a canvas with EasyX, you can directly use the coordinates on the canvas to avoid errors.
7. Operation error, the side length output of the rectangle is empty. The reason is that the space between the coordinates is too small and the characters overlap each other. As a result, all of them cannot be displayed. Just increase the distance between the characters.

Fourth, the results
1) fork function creates a parent and child
Insert picture description here
fork () function context return different values in different processes, returns pid child process is the parent process, returns 0 in the child, if the error is a negative number;
output The first sentence is the pid of the current process and its parent process, the current process pid is 18239, and then the child process is created. The pid is 18240 in the parent process and 0 in the child process; the second sentence output is the output of the parent process. The three sentences are output from the child process.

2) The pthread_create function creates two threads
Insert picture description here
Insert picture description here
. As can be seen from the figure, the two threads run successfully concurrently.

3) VS environment realizes the function of (2)
Insert picture description here

It can be seen from the figure that the two threads run successfully concurrently.

4) VS environment simulation to achieve the "producer-consumer" problem
Insert picture description here
. As can be seen from the picture, the production and consumption of both the producer and the consumer are executed at the same time without delay to each other, and the number of accesses and the numbers taken out in the buffer are correct.

5) VS environment draws circles and squares concurrently
Insert picture description here
Insert picture description here
Insert picture description here
. It can be seen from the figure that the two-threaded concurrent drawing of circles and squares is successfully achieved.

V. Experience
Through this experiment, I have a preliminary understanding of parent-child processes and multithreading. I can understand the meaning of PV operation and master its usage. I can deal with some problems more skillfully in future programming; but the current level of proficiency is still Not enough, still need more practice.

Guess you like

Origin blog.csdn.net/weixin_45341339/article/details/112412788