“Have you anything to say? If not, I’ll do it, “the kill program finally asks.

This time I did not answer.

My short life ended like this…

I’m a web program that has been running Windows all my life and living comfortably. But some time ago, the programmer told me to transplant me to run under the Linux system, I need a major operation, so my peaceful life was shattered.

Coming to this place called Linux to run, everything is very strange to me. Instead of the familiar C, D and E disks, there are all kinds of directories.

/bin
/boot
/etc
/dev
/mnt
/opt
/proc
/home
/usr
/usr64
/var
/sys
...
Copy the code

It’s funny. Everything is a file. The hardware is a file, the pipes are a file, the network sockets are a file.

It’s all fine. I’m okay with it, but until today

Strange fork

This morning, I received a network request, which needs to complete a function. This work is time-consuming, SO I plan to create a sub-process and let my younger brother finish it.

This was my first time creating a process on Linux, and I was a bit confused. All I saw was that the programmer had written a fork in my code:

pid_t pid=fork(); If (pid > 0) {...} else if (pid = = 0) {...} else {...}Copy the code

I stagger to the door of fork and look around.

“Are you creating a process?” The fork function seems to see where I’m coming from.

“Yes, I’m creating a process here for the first time. When I was on Windows, I used to call CreateProcess, but I don’t think there’s a function with that name…”

The fork function laughed and said, “Forget it. I’m the function that created the process.”

“Are you? Fork means “fork” or “fork”. “I said, heading for the fork function.

Fork ignored my question and simply said, “Take a seat while I communicate with the kernel to create a child process.”

The creation of processes is done by system calls in the kernel of the operating system, whereas functions such as fork are simply interfaces to the application layer, just as they were on Windows.

“Alas,” I asked, “I haven’t told you the parameters of the process to be created. How do you know which program to start?”

Fork chuckled, but didn’t answer my question.

Life is not familiar, I have no good to ask more, had to wait patiently, during the waiting I actually fell asleep.

“Wake up!” after an indefinite amount of time, the fork function woke me up: “Creation completed, please hold, this is process ID PID” and gave me a number.

I spread it out and found a big 0!

“Why did it fail?” “I asked.

“No, you are the child process you just created.”

“What? Are you mistaken? I came to create a child process. How can I be a child process?”

The fork function laughs again, “I’m not mistaken, you’re not you anymore, you’re a copy, just copied by the kernel.”

“A copy? What do you mean?” The more I listen to the more confused!

“Each process in the kernel is a task_struct structure. While you were sleeping, the kernel created a copy of your task_struct and created a new process address space and stack. Now you are basically the same as you were before, except in a few ways.”

“What about the old me? Where did it go?”

“It has become your parent. I am a special function that returns twice in one call, in both the parent and the child. In the original process, I gave him your process number, and I give you back 0, which means you are now the child process.”

I was struck by the fact that there is such a strange function that once it is called, it becomes two processes, and I suddenly understand why the function is called fork.

copy-on-write

“You are just come to us here, may not be too familiar with, slowly get used to it”

“You this efficiency is too high, the whole process address space is so large, incredibly so quickly copied a copy!”

The fork function laughs again! Did I say the wrong thing again?

“The memory address space of the process is not copied. You now share the memory space with the parent process.”

“What? Shared? Didn’t you just say you created a new process space and stack?”

“The memory address space you see is virtual. Your memory page and the parent’s memory page are actually mapped to the same physical memory page, so they are actually shared.”

“So it is, but made into a shared, two processes used together, isn’t there trouble?”

“Don’t worry, the kernel makes these pages read only. If you just read, there will be no problem, but as soon as one of you tries to write, an exception will be raised, and the kernel will find an exception and allocate a new page for you to use separately. Oh, it’s called copy-on-write.”

“That’s interesting. You guys are smart.”

“There is no way to reduce the cost and increase the efficiency of creating a process, because many of the pages in the process will only be read. It would be a waste of resources and time to copy all the pages mindlessly,” says the fork function.

“Fair enough, fair enough,” I nod, say goodbye to the fork function, and get back to work.

Missing threads

I thought this strange way of creating processes was an eye-opener, but something terrible was just beginning.

Shortly after leaving the fork function, I was stuck in a place where I couldn’t execute because there was a lock in front of me that was being held by another thread and I now needed to hold it.

This is not surprising, in my previous work, I often encountered the situation that the lock was locked by another thread, but this time, I waited for a long time but there was no thread to release.

“Hey, wake up.”

I don’t know how long later, I actually fell asleep again.

Opening my eyes, another program station appeared in front of me.

“And you are?”

“Hello, I’m Kill.”

“Kill? The kill program that kills processes? Why do you come to me? “I was startled to sleep.

The kill program picks up two numbers from behind: 9,1409

“Look, this is the parameter I received. 1409 is your process number PID, and 9 means to forcibly kill you.”

“Ah? Why?” At that moment, I completely panicked.

“Maybe you’ve been stuck here for so long that the humans started me to stop you,” the kill program says.

“Yeah, some damn thread is holding on to the lock and I’m stuck,” I complained.

“Where is the other thread, I looked, you only have one thread this process ah!”

“Are you mistaken?” “, say that finish, I carefully checked up, actually still really only a thread! I waited so long for nothing!

“Strange, I clearly is a multithreaded program!” “I frowned.

“Think carefully. Did anything happen?” “The kill program asks.

“I just fork it, and it generates a child, and I’m that child.”

“No wonder! “, the kill program suddenly realized.

“No wonder what?

“When the fork guy creates a child process, it only copies the current thread, no other threads are copied!” “, the Kill program sighed, as if it had become familiar.

“What? How did that happen? If other threads don’t copy, what’s going to happen?”

The kill program takes its time and says: In the early days of single-threaded programs, a task_struct was a process, and there was no problem with forking. Later, multithreading came along, where a task_struct was actually a thread, and multiple task_structs shared address space. Become a thread group, that is, a process, but fork still copies only the current thread, that’s the problem.”

“Damn it, fork!”

“You’re not the first one! Just wait for the programmers to remake you.”

“Alas…”, I sighed.

“Have you anything to say? If not, I’ll do it, “the kill program finally asks.

This time I did not answer.

See kill brother hand up and knife down, everything disappeared

【 the 】