Linux下C 执行shell命令的方法总结

1.system()系统调用

extern int system (const char *__command) __wur;
例子:
system("ls -l ./");

注意:此函数是阻塞调用的。 

2.、使用vfork()新建子进程,然后调用exec函数族

这里对fork()和vfork()函数做一点说明:vfork函数的调用序列和返回值都和fork相同,但两者语义不同。vfork函数用于创建一个新进程,而该新进程的目的是exec一个新程序。vfork与fork一样会创建一个子进程,但是它并不会将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec(或者exit),于是也就不会引用该地址空间。不过如果在子进程调用exec或者exit之前,它在父进程的空间中运行。但是如果子进程修改数据、进行函数调用、或者在没有调用exec或exit之前就返回可能会带来未知的结果。

fork和vfork的另一个区别是:vfork保证子进程先执行,在它调用exec或exit之后父进程才可能被调度运行。(如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则导致死锁)

#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include <string>

int main(int argc, char *argv[])
{	
	int ret = -1;
	pid_t pid = vfork();
	if (pid < 0) {
		
		return -1;
	}
	else if(pid == 0) {
		
		char *argv_1[] = {"", "/home/ubuntu64/linux-pro/2.txt", (char *)0};
		ret = execv("./file1", argv_1);
		if (ret < 0) {
			
			return -1;
		}
	}
	else {
	
		printf("process parent ......\n");
		waitpid(pid, NULL, 0);
	}
	
	return 0;
}

 程序中waitpid控制子进程执行完之后父进程再退出。

3.popen()函数

extern FILE *popen (const char *__command, const char *__modes) __wur;

popen()也会调用fork()产生子进程,然后从子进程中调用/bin/sh -c来执行参数command的指令。参数type可使用“r”代表读取,“w”代表写入。依照此type值,popen()会建立管道连到子进程的标准输出设备或标准输入设备,然后返回一个文件指针。随后进程便可利用此文件指针来读取子进程的输出设备或是写入到子进程的标准输入设备中。此外,所有使用文件指针(FILE*)操作的函数也都可以使用,除了fclose()以外。

#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>

int main(int argc, char *argv[])
{

    FILE *fp = NULL;
    char buffer[1024] = { 0 };
	
    fp = popen("ls -l", "r");
	
    fread(buffer, 1, 1000, fp);
    printf("%s", buffer);
    pclose(fp);

    return 0;
}

4.forkpty()函数

这是SSH服务器的标准实现方法!

#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include<string>
#include <pty.h>
#include <utmp.h>
using namespace std;

void getpwd(int fd, char *buf)
{
	write(fd, "pwd\n", strlen("pwd\n"));
	read(fd, buf, 1024);
}

int main(int argc, char *argv[])
{	
	int masterFd;
	pid_t pid = forkpty(&masterFd, NULL, NULL, NULL);
	string terminal = string(::getenv("SHELL"));
	printf("%s\n", terminal.c_str());
	switch(pid){
	case -1:
	{

	}
	break;
	case 0:{
		terminal = string(::getenv("SHELL"));
		execl(terminal.c_str(), NULL, NULL);
		printf("child process exit...?\n");
		exit(0);
	break;
	}
	default:{
	
	    printf("child pid is %d\n", pid);
	break;
	}
    }
	char pwdbuf[1024] = { 0 };
	getpwd(masterFd, pwdbuf);	
	write(masterFd, "ls -l /\n", strlen("ls -l /\n"));
	
	char buf[2048] = { 0 };
	read(masterFd, buf, 2046);
	printf("%s", pwdbuf);
	printf("%s\n", buf);
	
	write(masterFd, "cd /\n", strlen("cd /\n"));
	memset(buf, 0, 2048);
	read(masterFd, buf, 2046);
	memset(pwdbuf, 0, 1024);
	getpwd(masterFd, pwdbuf);
	printf("%s", pwdbuf);
	printf("%s\n", buf);

	write(masterFd, "ls -l ~/\n", strlen("ls -l ~/\n"));
	memset(buf, 0, 2048);
	read(masterFd, buf, 2046);
	printf("%s", pwdbuf);
	printf("%s\n", buf);	
	
	return 0;
}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值