fgets()是否锁定stdout从而防止printf

时间:2018-12-11 20:53:55

标签: c multithreading printf fgets ecos

我有一个带有两个线程的C程序,这些线程之一几乎一直被fgets()阻塞,等待用户输入。第二个线程可能需要打印到终端,而第一个线程在fgets()上被阻止。

从我的测试看来,该程序等待第一个线程上的fgets()返回,然后第二个线程才能打印。

这是谁的作品,还是在fgets()上另一个线程被阻塞时我可以打印?

此实现在eCos(嵌入式可配置操作系统)上运行。

线程已锁定在fgets()上:

int my_getline (char** argv, int argvsize)
{
    static char line[MAX_LINE];
    char *p;
    int argc;

    fgets(line, MAX_LINE, stdin);


    for (argc=0,p=line; (*line != '\0') && (argc < argvsize); p=NULL,argc++) {
        p = strtok(p, " \t\n");
        argv[argc] = p;
        if (p == NULL) return argc;
    }
    argv[argc] = p;
    return argc;
}

尝试打印的线程:

while(1){
        unsigned char bufr[50];
        read_until(bufr);
        if (bufr[1] == (unsigned char)NMFL ){
            cyg_mutex_lock(&scree_mtx);
            printf("Memory half full!\n");
            cyg_mutex_unlock(&scree_mtx);
            continue;
        }
        cyg_mbox_put( mbx_serial_userH, bufr );     
}

输出(我确定该消息之前已经存在):

Output

1 个答案:

答案 0 :(得分:2)

C标准根本没有指定标准输入流和标准输出流之间的任何关联。尤其是,它没有指定一个线程通过任何标准函数从标准输入读取时阻塞应该导致任何输出函数阻塞。

但是,该标准也没有相反的说法,即一个阻塞来自create table Admini( Admin_ID number(8) primary key, EmployeeID number(8) references EmployeeInformation(EmployeeID), BookingID number(8) references Booking(BookingID) ) create table Booking( BookingID number(8) primary key, CustomerID number(8) references Customer(CustomerID), VehicleID number(8) references vehicle(VehicleID), AdminID number(8) references Admini(AdminID), BookingDate date not null, BookingDestination varchar2(30) not null, NumPassengers number(6) not null, SecondDriverNeeded varchar2(5) check(SecondDriverNeeded in('TRUE','FALSE')), DrivingDuration number(3) not null ) create table Customer( CustomerID number(8) primary key, CompanyName varchar2(30) not null, ContactName varchar2(30) not null, CustomerAddress varchar2(30) not null, CustomerEmail varchar2(30) not null, ContactNumber number(10) not null ) create table Driver( DriverID number(8) primary key, EmployeeID number(8) references Admini(AdminID), DLicenseNum varchar2(16) references DLicense(DLicenseNum), PCVSerialNum number(20) references PCV(PCVSerialNum), CPCSerialNum number(20) references CPC(CPCSerialNum), DrugTestID number(8) references DrugTest(DrugTestID), DriverBreakLength number(3) not null ) create table CPC( CPCSerialNum number(20) primary key, CPCExpiryDate date not null ) create table DLicense( DLicenseNum varchar2(16) primary key, DLExpiryDate date not null, PenaltyPoints number(2) not null ) create table DrugTest( DrugTestID number(8) primary key, TestDate date not null, TestResults varchar2(8) check(TestResults in ('POSITIVE','NEGATIVE')), TestType varchar2(7) check(TestType in ('DRUG','ALCOHOL','BOTH')) ) create table EmployeeInformation( EmployeeID number(8) primary key, EmployeeFirstName varchar2(30) not null, EmployeeLastName varchar2(30) not null, EmployeeAddress varchar2(30) not null, EmployeeHomePhone number(10) not null, EmployeeDOB date not null, EmployeeGender varchar2(6) check(EmployeeGender in ('MALE','FEMALE','OTHER')), EmployeePosition varchar2(6) check(EmployeePosition in ('ADMIN','DRIVER')), EmployeeInsuranceNum varchar2(9) unique, EmployeeSalary number(10) not null ) create table PCV( PCVSerialNum number(20) primary key, PCVExpiryDate date not null ) create table Vehicle( VehicleID number(8) primary key, DriverID number(8) references Driver(DriverID), VehicleAvailable varchar2(5) check(VehicleAvailable('TRUE','FALSE')), VehicleRate number(4) not null, VehicleModel varchar2(10) not null, VehicleMake varchar2(10) not null, DateOfRegistration date not null, RegistrationNumber number(8) unique, VehicleColour varchar2(10) not null ) 的输入的线程一定不会导致另一个阻塞到stdin的输出。是否发生这种情况将取决于C实现,并且可能取决于与stdoutstdin相关联的特定设备。

您似乎正在使用Windows C实现,其中stdoutstdin都连接到CMD.EXE窗口。 Windows有很多特质,我倾向于猜测您观察到的阻止就是其中之一。我不希望在Linux或OSX上出现相同的情况,但这并不意味着它是错误的。