创建进程
在Linux中,创建进程的主要函数是fork()
,它会复制当前进程的地址空间、堆、栈、寄存器等资源,创建一个新的子进程。fork()
函数没有参数,返回值是一个pid_t
类型的整数,表示进程的标识符。如果返回值为0,表示当前是子进程;如果返回值大于0,表示当前是父进程,返回值是子进程的标识符;如果返回值小于0,表示创建进程失败,可以通过errno
变量获取错误码。
创建进程后,父进程和子进程的执行顺序是不确定的,取决于操作系统的调度算法。如果想要在父进程中等待子进程结束,可以使用wait()
或waitpid()
函数,它们的参数和返回值如下:
wait(int *status)
:等待任意一个子进程结束,如果没有子进程,返回-1。参数status
是一个指针,用于存储子进程的退出状态,可以通过一些宏来判断子进程是正常退出还是异常终止,以及退出码或信号值。返回值是结束的子进程的标识符,或者-1表示出错。waitpid(pid_t pid, int *status, int options)
:等待指定的子进程结束,或者满足一些条件。参数pid
是要等待的子进程的标识符,如果为-1,表示等待任意一个子进程,与wait()
相同。参数status
与wait()
相同,用于存储子进程的退出状态。参数options
是一些标志位,用于控制函数的行为,比如是否阻塞等待,是否等待已停止的子进程等。返回值与wait()
相同,是结束的子进程的标识符,或者-1表示出错。
下面是一个简单的示例,演示了如何使用fork()
和wait()
函数创建和等待进程:
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
using namespace std;
int main()
{
cout << "I am the parent process, my pid is " << getpid() << endl;
pid_t pid = fork(); // create a child process
if (pid == 0) // child process
{
cout << "I am the child process, my pid is " << getpid() << endl;
sleep(3); // simulate some work
cout << "I am the child process, I am done" << endl;
return 0; // exit normally
}
else if (pid > 0) // parent process
{
cout << "I am the parent process, I created a child process with pid " << pid << endl;
int status;
pid_t child_pid = wait(&status); // wait for any child process to end
if (child_pid == -1)
{
perror("wait error");
return -1;
}
if (WIFEXITED(status)) // child process exited normally
{
cout << "I am the parent process, my child process " << child_pid << " exited with code " << WEXITSTATUS(status) << endl;
}
else // child process terminated abnormally
{
cout << "I am the parent process, my child process " << child_pid << " terminated by signal " << WTERMSIG(status) << endl;
}
cout << "I am the parent process, I am done" << endl;
return 0;
}
else // fork error
{
perror("fork error");
return -1;
}
}
输出结果可能是:
I am the parent process, my pid is 1234
I am the parent process, I created a child process with pid 1235
I am the child process, my pid is 1235
I am the child process, I am done
I am the parent process, my child process 1235 exited with code 0
I am the parent process, I am done
创建线程
在Linux中,创建线程的主要函数是pthread_create()
,它会在当前进程的地址空间中创建一个新的执行流,与其他线程共享堆、全局变量、静态变量等资源,但有自己的栈、寄存器、程序计数器等。pthread_create()
函数的参数和返回值如下:
pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg)
:创建一个新的线程,并让它执行指定的函数。参数thread
是一个指针,用于存储新创建的线程的标识符。参数attr
是一个属性对象,可以用来设置线程的属性,如栈大小、优先级等,如果使用默认值,可以传入NULL。参数start_routine
是一个函数指针,指向线程要执行的函数,该函数的参数和返回值都是void *
类型的指针,可以用来传递任意类型的数据。参数arg
是传递给线程函数的参数,必须强制转换为void *
类型。返回值是一个整数,如果为0,表示创建线程成功,否则表示失败,可以通过errno
变量获取错误码。
创建线程后,线程的执行顺序也是不确定的,取决于操作系统的调度算法。如果想要在主线程中等待子线程结束,可以使用pthread_join()
函数,它的参数和返回值如下:
pthread_join(pthread_t thread, void **retval)
:等待指定的线程结束,并获取它的返回值。参数thread
是要等待的线程的标识符。参数retval
是一个指针的指针,用于存储线程函数的返回值,如果不关心返回值,可以传入NULL。返回值是一个整数,如果为0,表示等待线程成功,否则表示失败,可以通过errno
变量获取错误码。
下面是一个简单的示例,演示了如何使用pthread_create()
和pthread_join()
函数创建和等待线程:
#include <iostream>
#include <pthread.h>
using namespace std;
// the thread function
void *say_hello(void *args)
{
cout << "Hello, I am a new thread, my tid is " << pthread_self() << endl;
return (void *)0; // return normally
}
int main()
{
cout << "I am the main thread, my pid is " << getpid() << ", my tid is " << pthread_self() << endl;
pthread_t tid; // the thread identifier
int ret = pthread_create(&tid, NULL, say_hello, NULL); // create a new thread
if (ret != 0) // error occurred
{
perror("pthread_create error");
return -1;
}
cout << "I am the main thread, I created a new thread with tid " << tid << endl;
void *retval;
ret = pthread_join(tid, &retval); // wait for the new thread to end
if (ret != 0) // error occurred
{
perror("pthread_join error");
return -1;
}
cout << "I am the main thread, my new thread ended with retval " << (long)retval << endl;
return 0;
}
输出结果可能是:
I am the main thread, my pid is 1234, my tid is 140735803338496
I am the main thread, I created a new thread with tid 140735795945216
Hello, I am a new thread, my tid is 140735795945216
I am the main thread, my new thread ended with retval 0