当前位置:文档之家› 实验十七 Linux下进程线程的创建

实验十七 Linux下进程线程的创建




父进程创建子进程后,子进程一般要执行不同的程 序.为了调用系统程序,我们可以使用系统调用 exec 族调用。 Exec函数可以把当前进程替换为一个新进程 exec函数包含以下五个函数:
#include<unistd.h> int execl(constchar* path, const char* arg, …); int execlp(constchar* file, const char* arg, …); int execle(constchar* path, const char* arg, char* const envp[]); int execv(constchar* path, char* const argv[]); int execvp(constchar* file, char* const argv[]);
4.11 Fibonacci序列是一组:0,1,1,2,3,5,8,…… fib0=0; fib1=1; fibn=fibn-1+fibn-2; 使用phtread多线程编程程序来生成Fibonacci序列。 程序应该这样工作:用户运行程序时,在命令行输 入要产生Fibonaci序列数,然后程序创建一个新的 线程来产生Fibonacci数,把这个序列放到线程共 享的数据中(数组可能是一种最方便的数据结构)。 当线程执行完成后,父线程将输出子线程产生的序 列。由于在子线程结束前,父线程不能开始输出 Fibonacci序列,因此,父线程需要等子线程结束
等待线程结束,收集线程信息 参数1.指定了将要等待结束的线程 参数2. 是一个指针,指向了一个指针,后者指向线 程的返回值
例子
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> void *thread_function(void *arg); char message[] = "Hello world"; int main(){ int res; pthread_t a_thread; void *thread_result; res = pthread_create(&a_thread,NULL,thread_function,(void*)message); if(res !=0){perror("Thread creation failed"); exit(EXIT_FAILURE);} printf("Waiting for thread to finish..\n");
4/19/2013
Linux进程创建


Linux进程的族亲关系
Linux进程之间不是孤立存在的,它们之间有一定的族亲关系。
产生
进程1
进程2
父进程

子进程
一个进程的子进程可以多于一个。 一个进程只会有一个父进程。
Linux进程创建

系统加电启动后,系统中只有一个进程——初始化 进程,又称init进程,是所有进程的祖先进程,它 的进程pid=1 在linux中除了init进程是由系统启动时创建的外, 其他所有进程都是由当前进程使用系统调用fork() 创建的。 进程创建后父子进程在系统中并发执行。

4/19/2013
Linux 创建线程

线程:一个进程内部的一个控制序列 每个进程都至少有一个执行线程
创建线程与fork区别
fork: 当前进程的拷贝,有自己的变量和PID,时 间调度独立,执行几乎完全独立于父进程 新线程:有自己独立栈(有局部变量) 但与创建者共享全局变量,文件描述,信号句柄和 当前状态等
Linux下进程和线程的创建
吴国伟

学习Linux中创建进程的方法 学习系统调用Fork的使用方法 学习系统调用Exec族的使用方法

学习Linux中创建线程的方法 学习pthread_create使用方法

PID:进程号。 PPID:父进程号。


UID:其创建者的用户标识号,父子进程有相同 的UID值。
int pthread_create( pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void*), void *arg) 参数 1. 该指针指向的变量中将被写入一个标识符,用 该 标识符来引用新线程 2. 设置线程属性,一般不用设为null 3. 表示线程将要启动执行的函数 4. 该函数需要的参数 调用成功返回值为0,否则返回错误代码
◦ 父进程:返回子进程的PID;
最初的进程
◦ 子进程:返回0;
◦ 出现错误:返回-1;
fork()
返回一个 新的pid 返 回 0
原进程继续 执行
新进程
#include <unistd.h> #include <sys/types.h> #include <stdio.h> int main() { int pid = fork(); if (pid == -1 ){ printf("error!\n"); } else if( pid == 0 ) { printf("This is the child process!\nchild process id = %d\n",getpid()); } else { printf("This is the parent process!\nparent process id = %d\n",getpid()); } return 0;}
res = pthread_join(a_thread, &thread_result); if(res !=0){perror("Thread join failed"); exit(EXIT_FAILURE);} printf("Thread joined, it returned %s\n",(char*)thread_result); printf("Message is now %s\n",message); exit(EXIT_SUCCESS); } void *thread_function(void *arg){ printf("thread_function is running. Argument was %s \n",(char *)arg); sleep(3); strcpy(message,"Bye!"); pthread_exit("Thank you for the CPU time"); }

此时一个进程“分裂”成两个进程:父进程和子进程。
区别:进程ID。利用getpid()来得到进程号。


通过fork创建一个新进程,系统复制当前进程,在进程表中创建一个新的表 项 新进程几乎与原进程相同,执行代码也相同 但有自己的数据空间,环境,文件描述符等


Fork()系统调用

fork调用的一个奇妙之处就是它仅仅被调用一次, 却能够返回两次,它可能有三种不同的返回值:

线程优缺点


优点: 一般而言,线程创建以及线程之间的切换需要操作 系统做的工作比进程少得多。 例子:编辑文档过程的多线程,一个线程负责用户 输入和编辑,一个线程负责字数统计


缺点: 多线程程序因变量共享可能引发潜在错误,调试困 难
pthread_creat



运行结果
Waiting for thread to finish... thread_function is running. Argument was Hello world Thread joined, it returned Thank you for the CPU time Message is now Bye!
#include<sys/types.h> #include<sys/wait.h> pid_t wait(int *stat_loc) 父进程调用
1. wait系统调用将暂停父进程直到它的子进程结束为止 2. 返回子进程的PID 3. 状态信息允许父进程了解子进程的退出状态,即子进程 main函数返回值或子进程中exit函数的退出码 4. 若stat_loc不为空指针,状态信息被写入他指定的为止
4/19/2013

其中只有execve是真正意义上的系统调用,其它 都是在此基础上经过包装的库函数。 #include<unistd.h> intexecve(constchar* path, char* const argv[], char* const envp[]);
◦ path:可执行文件路径。 ◦ argv[]:要执行的文件名或命令名。 ◦ envp[]:环境变量,可省略
4/19/2013

运行结果: This is the child process! child process id = 4800 This is the parent process! parent process id = 4799

4/19/2013
Fork()系统调用
等待一个进程结束
void pthread_exit(void *retval)

调用上面函数终止线程 返回一个指向某个对象的指针 注意:不能用它来返回一个指向局部变量的指针, 因为线程调用该函数后,这个局部变量就不存在了
pthread_join

int pthread_join( pthread_t th, void **thread_return)
相关主题