进程

进程

一、主要函数:fork();wait();waitpid();exec 家族;system();

   其它函数: getppid();getrlimit();atexit();strtok();getline();
二、

1 fork() 用于创建一个子进程
  1)
父进程中,在fork 之后修改全局变量的值,不会影响到其子进程的变量
  2)
子进程中修改变量的值并不影响父进程中该变量的值,即使这个变量为全局变量
  3)
一般父进程先执行。
  4)
但是,父、子对文件的操作是互相影响的 .(父子进程共享文件的亚信息)
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int x=0;
int main(void)
{
  x++;
  printf("x=%d/n",x);
  pid_t pid;
  pid=fork();
  x++;
  if(pid==0)
  x++;
  printf("child x=%d",x);
  exit(0);
  }
  exit(0);
}
2
wait();waitpid(); 回收僵尸

只要用了wait, 当没有进程退出时就会处于阻塞。
The call wait(&status) is equivalent to:     waitpid(-1, &status, 0);
WNOHANG     return immediately if no child has exited.
非阻塞:Waitpid(-1,NULL,WNOHANG);/ /第一个参数-1 表示任何子进程。第一个参数> 0    meaning  wait  for  the  child  whose process ID is equal to the value of pid.

3
exec 家族
execl(“/bin/ls”,”ls”,”-a”,“-l”NULL);
execv(“/bin/ls”.........................);
execlp(“ls”,”ls”,”-a”,”-l”,NULL);
execvp()
需要构造 char* argv[4]={“ls””-al””./””NULL”};
execvp(“ls”,argv);
 

4 /*getppid() 取得父进程 PID*/
5
system()

include<stdlib.h> 定义函数int system(const char * string);

函数说明:system() 会调用fork() 产生子进程,由子进程来调用/bin/sh-c string 来执行参数string 字符串所代表的命令,此命> 令执行完后随即返回原调用的进程。在调用system() 期间SIGCHLD 信号会被暂时搁置,SIGINTSIGQUIT 信号则会被忽略。

返回值 =-1: 出现错误

       =0: 调用成功但是没有出现子进程

       >0: 成功退出的子进程的id

如果system() 在调用/bin/sh 时失败则返回127 ,其他失败原因返回-1 。若参数string 为空指针(NULL) ,则返回非零值> 。如果system() 调用成功则最后会返回执行shell 命令后的返回值,但是此返回值也有可能为 system() 调用/bin/sh 失败所返回的127 ,因此最好能再检查errno 来确认执行成功。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(void)
{
  char *linePtr = NULL;
  int ret, size;
  while (1) {
  printf("%%:");
  fflush(stdout);
  ret = getline(&linePtr, &size, stdin);
  if (linePtr[ret-1] == '/n')
  linePtr[ret-1] = '/0';
  system(linePtr);//
传入命令行及参数
  }
}
三、例程:

1

/*waitpid.c*/
#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main(void)
{
    pid_t pid;
    int ret;
 
    pid = fork();
    if (pid == -1) {
        perror("fork");
        exit(1);
    }
 
    if (pid == 0) {
        sleep(2);
        exit(0);
    }
 
    if (pid > 0) {
        while (1) {
            if (ret = waitpid(
                0, NULL, WNOHANG)) {
                break;
            } else if (ret == 0){
                printf("x");
                fflush(stdout);
                continue;
            }
        }
    }
 
    exit(0);
}

2

/*zombie.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
#define CHILDNUM 1
 
int main(void)
{
    int i;
    pid_t pid;
    for (i = 0; i < CHILDNUM; i++) {
        pid = fork();
        if (pid == 0) {
            sleep(1000);
            exit(0);
        }
    }
 
#if 1     
    for (i = 0; i < CHILDNUM; i++) {
        wait(NULL);    
    }
#endif
    while (1) { 
        printf("Hello!/n"); 
        sleep(1);
    }
}
/*用wait()收僵尸*/

3

/*fd_fork.c*/
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>

int main(void)
{
    int fd=open("/etc/passwd-",O_RDONLY);
    pid_t pid=fork();
    if(pid==-1)
    {
        perror("fork");
        exit(1);
    }
    if(pid==0)
    {
        int ret;
        char buf[32];

        ret=read(fd,buf,31);
        buf[ret]='/0';
        printf("child read=%s/n",buf);
        exit(0);
    }
    if(pid>0)
    {
        int ret;
        char buf[32];

        ret=read(fd,buf,31);
        buf[ret]='/0';
        printf("father read=%s/n",buf);
//        lseek(fd,0,SEEK_SET);//
        close(fd);//
        wait(NULL);
        exit(0);
    }
}
/* 父进程读一次(31个字节)后,子进程接着读下去,即使在父进程close(fd),子进程也还是会接着读下去的。(因为此时fd并没有真正被释放)。
 * 但是如果在父进程中lseek(fd,0,SEEK_SET)的话,那么子进程会从文件头开始读。*/
/* 所以说父进程和子进程对文件的操作是比较特殊的,它们对文件的操作是互相
 * 影响的*/

4

/*fs.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
 
int main(void)
{
    int fd;
    pid_t pid;
    int ret;
    char buf[32];
 
    fd = open("/etc/passwd", O_RDONLY);
    if (fd == -1) {
        perror("open");    
        exit(1);
    }
 
    pid = fork();
    if (pid == -1) {
        perror("fork");
        close(fd);
        exit(1);
    }
    
    if (pid == 0) {
        sleep(1);
        while (1) {
            ret = read(fd, buf, 31);
            if (ret == 0) 
                break;
            buf[ret] = '/0';
            printf("%s", buf);
            fflush(stdout);
        }
        exit(0);
    }
 
    if (pid > 0) {
        ret = read(fd, buf, 31);
        buf[ret] = '/0';
        printf("%s   &&&& ", buf);
        fflush(stdout);
        close(fd);
        exit(0);
    }
 
    
}
/*父进程和子进程对文件的操作比较特殊,它们对文件的操作是互相影响的,它们是不是共享一个描述符呢?应该不是!如果让父进程写,子进程读呢?会是怎么样?*/

5

/*exec.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main(void)
{
//    int ret = execl("/bin/ls", "ls",  
//        "-al", "./", NULL);
 
    char *argv[4] = {
        "ls",
        "-al",
        "./",
        NULL
    };
 
    int ret = execvp("ls", argv);
    if (ret == -1) {
        perror("execlp");
        exit(1);
    } else {
        perror("execlp");
        exit(0);
    }    
}

6

//*dead.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
#define CHILDNUM 1
 
int main(void)
{
    int i;
    pid_t pid;
    for (;;) {
        pid = fork();
        if (pid == 0) {
            exit(0);
        }
    }
 
}
/*程序不停地fork子进程,然后子进程退出,但是由于没有回收僵尸,时间一长,就会由于系统次源不足而崩溃*/

7

/*getrlimit.c*/
#include <sys/resource.h>
#include <stdio.h>
 
int main(void)
{
    struct rlimit limit;
 
    getrlimit(RLIMIT_NPROC, &limit);
    printf("soft:%10ld, hard:%10ld/n", limit.rlim_cur, limit.rlim_max);
}

8

/*atexit.c*/
#include <stdio.h>
#include <stdlib.h>
 
void fun0(void)
{
    printf("%s/n", __func__);
}
void fun1(void)
{
    printf("%s/n", __func__);
}
 
int main(void)
{
    atexit(fun0);
    atexit(fun1);
    printf("hello world!/n");
    sleep(3);
    exit(0);
}
/*用atexit去注册在程序退出前还要执行的函数,
本例程中用atexit注册了fun0和fun1,程序退出前会去执行它们,
但是,先执行fun1,再执行fun0,因为执行的顺序与注册时的顺序是相反的*/

 

9

/*system.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
 
int main(void)
{
    char *linePtr = NULL;
    int ret, size;
    while (1) {
        printf("%%:");
        fflush(stdout);
        ret = getline(&linePtr, &size, stdin);
        if (linePtr[ret-1] == '/n')
            linePtr[ret-1] = '/0';
        system(linePtr);
    }
}

 

10

/*getpid,getppid*/
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{
    printf("my pid = %d. my parent pid = %d/n",
        getpid(), getppid());
    while (1)
        sleep(1);
    return 0;
}
/*要知道main这个进程也是被fork出来的*/

 

11

/*getline.c*/

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

 

#define TOKEN " "


void strParse(char *buf)

{

    char *ptr;

    char *ori = buf;

    while (1) {

        ptr = strtok(buf, TOKEN);

        if (ptr == NULL)

            break;

        buf = NULL;

        printf("%s/n", ptr);

    }

    free(ori);

}


int main(void)

{

    char *linePtr = NULL;

    int ret;

    size_t num;

    char *buf;

 

    while (1) {

        ret = getline(&linePtr, &num, stdin);

        buf = (char *)calloc(ret, 1);

        strncpy(buf, linePtr, ret-1);

        strParse(buf);     

    }

    if (linePtr)

        free(linePtr);

}

/*getline 用于读一整行,包括/n 也会读进来*/


12

/*strtok.c*/

#include <string.h>

#include <stdio.h>

 

 

int main(int argc, char **argv)

{

    char str[] = "ls &&& -a &&& -l &&& ./";

    char *token = " &";

    char *ptr, *strp = str;

    while (1) {

        ptr = strtok(strp, token);

        if (ptr == NULL)

            break;

        strp = NULL;

        printf("%s/n", ptr);

    }  

}

/*strtok 用于解析一个字符串,按照token 所指定的符号来解析。

解析的时候,strtok 的第一个参数第一次用strp, 以后每次都用NULL ,这是需要注意的*/

13

/* 理解函数指针的实例*/

 

#include <stdio.h>


void fun0(int s)

{

    printf("%d:%s/n", __LINE__, __func__);

}


void fun1(int s)

{

    printf("%d:%s/n", __LINE__, __func__);

}

 

#if 0

void (*a(int b)) (int s)

{

    return fun0;

}

#endif


typedef void (*handler) (int s);

 

handler a(int b)

{

    return fun1;

}

 

int main(void)

{

#if 0

    void (*handler) (int s);

    handler = fun0;

    handler(0);

    handler = fun1;

    handler(1);

#endif

    (a(3))(3);

    return 0;

}

/*

void (*a(int b)) (int s)// 是不是这样理解呢?a 是一个函数指针,所指向的函数的参数为int(int b), 所指向的函数的返回值又是一个函数,返回的这个函数的参数为int(int s), 无返回值

{

    return fun0;

}

*/

14

/*prime.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
#define BASE 300000000
 
typedef long long ll;
 
void do_prime(ll prime)
{
    ll i;
    int flag = 0;
    for (i = 2; i < prime; i++) {
        if (prime % i == 0) {
            flag = 1;
            break;
        }
    }
 
    if (flag == 0)
        printf("%lld is a prime!/n", prime);
    else    
        printf("%lld is a prime!/n", prime);
}
int main(void)
{
    int val, i;
    ll prime;
    pid_t pid;
 
    for (;;){
        printf("Please input vlaue:/n");
        scanf("%d", &val);
 
        prime = BASE + val;
        pid = fork();
        if (pid == 0) {
            do_prime(prime);
            exit(0);
        }  
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值