Go language Create New process process details (OS. StartProcess Source analysis)

Source: Internet
Author: User

on how to use the go language to achieve the creation of new processes and interprocess communication, I found a lot of information on the Internet, but I have not been able to find the answer to their satisfaction, so I intend to analyze this part of the source code, and then make good use of, and share to everyone, hoping that everyone can get inspiration from it.

First, let's look at a piece of code

Proc, _: = OS. StartProcess (name, args, attr)

If err! = Nil {

Fmt. PRINTLN (ERR)

}

_, Err = Proc. Wait ()

If err! = Nil {

Fmt. PRINTLN (ERR)

}

Let's take a look at this OS. What the hell did startprocess inside? and Proc. What did Wait () do again? Go into it with me.

StartProcess starts a new process with the program, arguments and attributes

specified by name, argv and attr.

//

StartProcess is a low-level interface. The Os/exec package provides

Higher-level interfaces.

//

If There is an error, it would be of type *patherror.

Func startprocess (name string, argv []string, attr *procattr) (*process, error) {

Return startprocess (name, argv, attr)

}

The note is that this function, which provides three parameters for opening a new process, is a low-level interface, while the Os/exec wrapper provides an advanced interface. If an error occurs here, it should be a pointer-type path fault.

Next we explore what startprocess is?

Func startprocess (name string, argv []string, attr *procattr) (p *process, err error) {

Sysattr: = &syscall. procattr{

Dir:attr. Dir,

Env:attr. Env

Sys:attr. Sys,

}


For _, F: = Range attr. Files {

Sysattr. Files = Append (sysattr. Files, F.FD ())

}


PID, h, E: = Syscall. StartProcess (name, argv, sysattr)

If E! = Nil {

return nil, &patherror{"Fork/exec", Name, E}

}


Return newprocess (PID, h), nil

}


First we see sysattr being given a &syscall. Procattr pointer, what is the structure of the procattr inside this syscall, to understand it first, so that it helps to understand that we use it to start the back Syscall

Procattr holds the attributes that would be being applied to a new process

Started by startprocess.

Type procattr struct {

If Dir is Non-empty, the child changes into the directory before

Creating the process.

Dir string

If Env is Non-nil, it gives the environment variables for the

New process in the form returned by Environ.

If It is nil, the result of Environ would be used.

ENV []string

Files specifies the open files inherited by the new process. The

First three entries correspond to standard input, standard output, and

Standard error. An implementation could support additional entries,

Depending on the underlying operating system. A Nil Entry corresponds

To, file being closed when the process starts.

Files []*file


Operating system-specific process creation attributes.

Note that setting this field means the Your program

May isn't execute properly or even compile on some

Operating systems.

Sys *syscall. Sysprocattr

}

The first sentence is straightforward, stating that the PROCATTR structure contains the values of the multiple attributes used during the process of initiating the process.

1) dir is the meaning of the directory, equivalent to the new process working directory, if configured will jump directory.

2) env refers to the list of environment variables for the new process.

3) files The first three items correspond to standard input, standard output and standard error output. Each implementation can support additional entries, and if the incoming entry is nil, the file is closed when the process starts.

4) Last *syscall. Sysprocattr is a system attribute, but the author also warns that some parameters may not work in cross-platform processes.

Now let's look at the *syscall. SYSPROCATTR structure.

Type sysprocattr struct {

Chroot string//Chroot.

Credential *credential//credential.

Ptrace BOOL//Enable tracing.

SETSID BOOL//Create session.

setpgid BOOL//Set Process group ID to new PID (SYSV setpgrp)

setctty BOOL//Set controlling terminal to FD 0

noctty bool//Detach FD 0 from controlling terminal

}

Credential holds user and group identities to be assumed

By a child process started by startprocess.

Type credential struct {

Uid UInt32//User ID.

Gid UInt32//Group ID.

Groups []uint32//supplementary group IDs.

}


You can see the properties involved in this area. (Partial properties do not work across platforms)

1) Chroot

2) credential including uid\gid\groups settings

3) Some bool attributes that participate in the process of setting up a new process.

Ptrace whether to allow tracing

Setsid whether to turn on SID

Setpgid whether to set the group ID to the new process

Setctty Whether you can use terminal access

The noctty separates the terminals from the fd0.


OK, now that we've learned so much, who's going to look at the code in front of you? As follows:

Func startprocess (name string, argv []string, attr *procattr) (p *process, err error) {

Sysattr: = &syscall. procattr{

Dir:attr. Dir,

Env:attr. Env

Sys:attr. Sys,

}


For _, F: = Range attr. Files {

Sysattr. Files = Append (sysattr. Files, F.FD ())

}


PID, h, E: = Syscall. StartProcess (name, argv, sysattr)

If E! = Nil {

return nil, &patherror{"Fork/exec", Name, E}

}


Return newprocess (PID, h), nil

}



Keep watching startprocess.

Sysattr: = &syscall. procattr{

Dir:attr. Dir,

Env:attr. Env

Sys:attr. Sys,

}

Dir working directory, ENV environment variable, Sys content is given to sysattr.

For _, F: = Range attr. Files {

Sysattr. Files = Append (sysattr. Files, F.FD ())

}

The files properties are arranged to be added to the sysattr so that we can give sysattr the overall contents of the attr *procattr parameter, and see how to use this sysattr

PID, h, E: = Syscall. StartProcess (name, argv, sysattr) sysattr passed in as the third parameter to the new

Syscall. StartProcess (name, argv, sysattr)

Note: Here we notice a problem and look at the code of our early period

Proc, _: = OS. StartProcess (name, args, attr)

If err! = Nil {

Fmt. PRINTLN (ERR)

}

This line of code is very similar to our initial code, so we understand that invoking the OS startprocess is called syscall.startprocess, so we understand that syscall.startprocess belongs to the underlying call. Os. StartProcess is the upper call. Os. Startproces just wrapped a layer outside the syscall.startprocess, so we understand that when we want to create a new process, as long as the parameters are already entered, we can either use the os.startprocess to implement, or use Syscall.sta Rtprocess to achieve. It is only important to note that the objects returned by the two are not the same.


How different?

We see the OS. StartProcess returns the return newprocess (PID, h), Nil, and

Syscall. StartProcess back is PID, H, E

That means the OS. The startprocess returned is syscall. StartProcess returns the result of the wrapper for the PID and H.

Process stores the information about a process created by startprocess.

Type Process struct {

Pid int

Handle UIntPtr

Isdone UInt32//process have been successfully waited on, non zero if True

}


Func newprocess (PID int, handle uintptr) *process {

P: = &process{pid:pid, Handle:handle}

Runtime. Setfinalizer (P, (*process). Release)

Return P

}

By observing the packaging process we understand that the purpose of returning this result is to deal with problems in the process of some programs. Below we need to understand the concept of running the program.

Runtime. Setfinalizer (P, (*process). Release) What is this line doing?

This part is difficult, if you understand this part will understand why the program packaging this layer, its purpose.

The following is a large section of English. Let me try to understand.

Setfinalizer sets the finalizer associated with X to F.

When the garbage collector finds an unreachable block

With an associated finalizer, it clears the association and runs

F (x) in a separate goroutine. This makes x reachable again, but

Now without an associated finalizer. Assuming that Setfinalizer

is not called again, the next time the garbage collector sees

That's X is unreachable, it'll free X.

//

Setfinalizer (x, nil) clears any finalizer associated with X.

//

The argument x must is a pointer to an object allocated by

Calling new or by taking the address of a composite literal.

The argument f must is a function that takes a single argument

To which X's type can assigned, and can have arbitrary ignored return

Values. If either of these is not true, Setfinalizer aborts the

Program.

//

Finalizers is run in dependency order:if A points at B, both has

Finalizers, and they is otherwise unreachable, only the finalizer

for A runs; Once A is freed and the finalizer for B can run.

If a cyclic structure includes a block with a finalizer, that

Cycle isn't guaranteed to be garbage collected and the finalizer

Is isn't guaranteed to run, because there are no ordering that

respects the dependencies.

//

The finalizer for X are scheduled to run at some arbitrary time after

X becomes unreachable.

There is no guarantee that finalizers would run before a program exits,

So typically they is useful only for releasing non-memory resources

Associated with an object during a long-running program.

For example, an OS. File object could use a finalizer to close the

Associated operating system file descriptor when a program discards

An OS. File without calling Close, but it would is a mistake

To depend in a finalizer to flush an in-memory I/O buffer such as a

Bufio. Writer, because the buffer would not being flushed at program exit.

//

It isn't guaranteed that a finalizer would run if the size of *x is

Zero bytes.

//

It isn't guaranteed that a finalizer would run for objects allocated

In initializers for package-level variables. Such objects May

linker-allocated, not heap-allocated.

//

A single goroutine runs all finalizers for a program, sequentially.

If a finalizer must run for a long time, it should does so by starting

A new goroutine.

I'm not here to copy English, just for the completeness of the article, let's see what it says. First we understand that this part of the code is in the garbage collection section, so I understand that we are getting closer to the bottom, and I have a hunch that this runtime. Setfinalizer (P, (*process). Release) should be a garbage collection mechanism for this newly initiated process, that is, how we can reclaim an already-completed process or a series of garbage data generated by the process running.

This article is from the "Technical Old man" blog, please be sure to keep this source http://allragedbody.blog.51cto.com/1352220/1747146

Go language Create New process process details (OS. StartProcess Source analysis)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.