XuQi's Blog

  • 首页

  • 归档

Linux进程

发表于 2018-04-25 更新于 2019-10-20

启动新进程的方式

1.system

system 并不是启动新进程的最佳选择。使用他启动新进程,依赖于shell和环境变量。

实验

1
2
3
4
5
6
7
8
9
10
#include <stdlib.h>
#include <stdio.h>
int main()
{
printf("Start Run px:\n");
system("ps ax");
printf("Done~\n");
exit(0);

}

输出:

1
2
3
4
5
6
7
8
9
10
11
  PID TTY      STAT   TIME COMMAND
1 ? Ss 0:00 /sbin/init
2 ? S 0:00 [kthreadd]
3 ? S 0:00 [ksoftirqd/0]
...
3834 ? S 0:00 /home/admini/private/9.dailystudy/04-26/system
3835 ? S 0:00 sh -c ps ax
3836 ? R 0:00 ps ax
Start Run px:
Done~
[Finished in 1.1s]

将system("ps ax");替换成system("ps ax &");

运行结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
Start Run px:
Done~
PID TTY STAT TIME COMMAND
1 ? Ss 0:00 /sbin/init
2 ? S 0:00 [kthreadd]
3 ? S 0:00 [ksoftirqd/0]
...
3862 ? S 0:00 gnome-pty-helper
3863 pts/0 Ss+ 0:00 bash
3877 ? S 0:00 [kworker/u4:0]
3888 ? Z 0:00 [bash] <defunct>
3898 ? R 0:00 ps ax
[Finished in 0.1s]

2.exec 替换进程印象

exec系列函数是由一组相关的函数组成,只是在启动方式和参数上不一致。
分为两大类:

  1. execl 参数个数不定,最后一个以空指针结束。
  2. execv 参数以数组形式提供。

以p结尾的函数,表示在PATH这个环境变量下找新的进程。

实验

1
2
3
4
5
6
7
8
9
10
#include <stdlib.h>
#include <stdio.h>
int main()
{
printf("Start Run px:\n");
system("ps ax");
printf("Done~\n");
exit(0);

}

输出:

1
2
3
4
5
6
7
 PID TTY      STAT   TIME COMMAND
1 ? Ss 0:00 /sbin/init
2 ? S 0:00 [kthreadd]
3 ? S 0:00 [ksoftirqd/0]

4126 ? S 0:00 bash -c gcc '/home/admini/private/9.dailystudy/04-26/exec.c' -o '/home/admini/private/9.dailystudy/04-26/exec' && '/home/admini/private/9.dailystudy/04-26/exec'
4134 ? R 0:00 ps ax

进程中没有原来的进程,而且输出结果中原来的输出也没有。

3.fork 复制进程映像

fork调用后,用同样的代码,创建一个子进程,子进程中fork调用返回0,父进程可以通过这点来判断谁是父,谁是子。
父子之间的变量是相互独立的。

实验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
pid_t pid;
char *message;
int n =0;

printf("========start=========\n");

pid = fork();

switch(pid)
{
case -1:
message = "Error\n";
break;
case 0:
message = "I'm Child~\n";
n= n + 3;
break;
default:
message = "I'm Fahter\n";
n = n +2;
break;
}

printf("%s",message);
printf("%d\n",n);
return 0;
}

输出:

1
2
3
4
5
6
7
========start=========
I'm Fahter
2
========start=========
I'm Child~
3
[Finished in 0.0s]

如果加上wait,父进程等待子进程退出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  ...
printf("%s",message);
printf("%d\n",n);

if (0 != pid)
{
int stat_val;
pid_t child_pid;
child_pid = wait(&stat_val);

printf("%s\n", "child finish");
}

return 0;

输出:

1
2
3
4
5
6
7
8
========start=========
I'm Child~
3
========start=========
I'm Fahter~
2
child finish
[Finished in 0.1s]

可以看到父进程的log输出在子进程后面。

僵尸进程

fork 处理来的子进程比父进程先结束,但是由于需要等待父进程,所以还在在进程表中。
这种情况他就是一个僵尸进程。

如果父进程异常终止,则子进程会挂到init进程中,永远没有机会释放。

wait是父进程等待挂起。waitpid不会挂起父进程,可以通过周期性的查询知道子进程的状态。

启动线程的方法:

int pthread_create(&threadid,NULL,thread_function,(void*)message);
第二个参数是线程的属性,一般情况设置为NULL,第3个参数是线程函数。

int pthread_join(threadid,&threadresult);
等待线程的结束,并取得返回退出的结果。退出的结果存在threadresult

pthread_exit(“end thread”);
结束线程,并返回结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

void *thread_function(void *arg);

char message[] = "hello world";

int main() {
int res;
pthread_t threadid;
// 不明白用成员变量指针为什么可以存储变量,不会出现错误修改内存的问题吗?
void *threadresult;

printf("create thread\n");

res = pthread_create(&threadid,NULL,thread_function,(void*)message);

if (res != 0) {
printf("create thread error!");
exit(1);
}

printf("wait thread end\n");
res = pthread_join(threadid,&threadresult);


if (res != 0) {
printf("join thread error!");
exit(1);
}

printf("get message from thread:%s\n",(char*)threadresult);
printf("current message is %s",message);
return 0;
}


void * thread_function(void *arg) {
int n = 3;
while(n>0) {
n--;
sleep(1);
printf("thread work!modify the message\n");
strcpy(message,"Bye!\n");
}

pthread_exit("end thread");
}

编译方法:

1
gcc ./thread.c -o thread -lpthread

运行结果:

sem_post(sem_t *sem);
1
2
3
4
5
6
7
create thread
wait thread end
thread work!modify the message
thread work!modify the message
thread work!modify the message
get message from thread:end thread
current message is Bye!

线程同步

信号量

信号量线程同步包括二进制信号量和计数信号量。

pshared是一直为0pshared
int sem_init(sem_t *sem, int pshared, unsigned int value);

int sem_post(sem_t *sem);

int sem_wait(sem_t *sem);

int sem_destroy(sem_t *sem);

# Linux基础
Scrapy 教程
树莓派上的Web Cam
  • 文章目录
  • 站点概览

XuQi

44 日志
30 标签
  1. 1. 启动新进程的方式
    1. 1.1. 1.system
    2. 1.2. 2.exec 替换进程印象
    3. 1.3. 3.fork 复制进程映像
    4. 1.4. 僵尸进程
  • 启动线程的方法:
    1. 0.1. 线程同步
    2. 0.2. 信号量
  • © 2019 XuQi
    由 Hexo 强力驱动 v3.9.0
    |
    主题 – NexT.Muse v7.3.0